﻿using FR.SAFTAnalyserLite.Services;
using FR.SAFTAnalyserLite.ViewModels.Workspace;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace FR.SAFTAnalyserLite.Model
{
    public partial class BaseData
    {
        string pk;
        /// <summary>
        /// Primary key of the registry
        /// </summary>
        [System.Xml.Serialization.XmlIgnore]
        public string Pk
        {
            get
            {
                if (string.IsNullOrEmpty(pk))
                    pk = Guid.NewGuid().ToString();
                return pk;
            }
            private set { pk = value; }
        }
    }

    public partial class SourceDocumentsPaymentsPayment : BaseData, IDataErrorInfo
    {
        SourceDocumentsPaymentsPaymentToolTipService tooltip;
        public SourceDocumentsPaymentsPaymentToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new SourceDocumentsPaymentsPaymentToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get
            {
                StringBuilder error = new StringBuilder();

                // iterate over all of the properties
                // of this object - aggregating any validation errors
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this);
                foreach (PropertyDescriptor prop in props)
                {
                    String propertyError = this[prop.Name];
                    if (propertyError != string.Empty)
                        error.Append((error.Length != 0 ? ", " : "") + propertyError);
                }

                return error.Length == 0 ? null : error.ToString();
            }
        }

        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "PaymentRefNo")
                {
                    erro = ValidatePaymentRefNo(appendError: true);
                }
                else if (columnName == "SourceID")
                {
                    erro = ValidateSourceID(appendError: true);
                }
                else if (columnName == "Period")
                {
                    erro = ValidatePeriod(appendError: true);
                }
                else if (columnName == "TransactionDate")
                {
                    erro = ValidateTransactionDate(appendError: true);
                }
                else if (columnName == "SystemID")
                {
                    erro = ValidateSystemID(appendError: true);
                }
                else if (columnName == "SystemEntryDate")
                {
                    erro = ValidateSystemEntryDate(appendError: true);
                }
                else if (columnName == "TransactionID")
                {
                    erro = ValidateTransactionID(appendError: true);
                }
                else if (columnName == "CustomerID")
                {
                    erro = ValidateCustomerID(appendError: true);
                }
                else if (columnName == "Description")
                {
                    erro = ValidateDescription(appendError: true);
                }

                return erro == null ? erro.Description : null;
            }
        }

        #region Validation
        public Error ValidatePaymentRefNo(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.PaymentRefNo) || this.PaymentRefNo.Length > 60)
            {
                erro = new Error { Description = "Identificação única com tamanho incorrecto.", Field = "PaymentRefNo", TypeofError = this.GetType(), Value = this.PaymentRefNo, UID = this.Pk };
                if (appendError)
                    this.Tooltip.PaymentRefNo = this.Tooltip.PaymentRefNo.FormatTooltipWithError(erro.Description);
            }
            else if (!Regex.IsMatch(this.PaymentRefNo, "[^ ]+ [^/^ ]+/[0-9]+"))
            {
                erro = new Error { Description = "Identificação única com caracteres não permitidos.", Field = "PaymentRefNo", TypeofError = this.GetType(), Value = this.PaymentRefNo, UID = this.Pk };
                if (appendError)
                    this.Tooltip.PaymentRefNo = this.Tooltip.PaymentRefNo.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidatePeriod(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.Period) == false)
            {
                int periodo = -1;
                Int32.TryParse(this.Period, out periodo);

                if (periodo < 1 || periodo > 12)
                {
                    erro = new Error { Description = string.Format("Mês do período de tributação do documento {0} incorrecto.", this.PaymentRefNo), Field = "Period", TypeofError = this.GetType(), Value = this.Period, UID = this.Pk };
                    if (appendError)
                        this.Tooltip.Period = this.Tooltip.Period.FormatTooltipWithError(erro.Description);
                }
            }

            return erro;
        }
        public Error ValidateTransactionID(bool appendError = false)
        {
            Error erro = null;

            if (!string.IsNullOrEmpty(this.TransactionID) && this.TransactionID.Length > 70)
            {
                erro = new Error { Description = string.Format("Identificador da transacção do documento {0} incorrecto.", this.PaymentRefNo), Field = "TransactionID", TypeofError = this.GetType(), Value = this.TransactionID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.TransactionID = this.Tooltip.TransactionID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateTransactionDate(bool appendError = false)
        {
            Error erro = null;

            if (this.TransactionDate < Workspace.Instance.Config.MinDate || this.TransactionDate > DateTime.Now)
            {
                erro = new Error { Description = string.Format("Data de emissão do documento {0} incorrecta.", this.PaymentRefNo), Field = "TransactionDate", TypeofError = this.GetType(), Value = this.TransactionDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.TransactionDate = this.Tooltip.TransactionDate.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateDescription(bool appendError = false)
        {
            Error erro = null;

            if (!string.IsNullOrEmpty(this.Description) && this.Description.Length > 200)
            {
                erro = new Error { Description = string.Format("Tamanho da descrição do recibo {0} incorrecto.", this.PaymentRefNo), Field = "Description", TypeofError = this.GetType(), Value = this.Description, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Description = this.Tooltip.Description.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidatePaymentStatusDate(bool appendError = false)
        {
            Error erro = null;

            if (this.DocumentStatus.PaymentStatusDate < Workspace.Instance.Config.MinDate || this.DocumentStatus.PaymentStatusDate > DateTime.Now)
            {
                erro = new Error { Description = string.Format("Data e hora do estado atual do recibo {0} incorrecta.", this.PaymentRefNo), Field = "PaymentStatusDate", TypeofError = this.GetType(), Value = this.DocumentStatus.PaymentStatusDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.PaymentStatusDate = this.Tooltip.PaymentStatusDate.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateReason(bool appendError = false)
        {
            Error erro = null;

            if (!string.IsNullOrEmpty(this.DocumentStatus.Reason) && this.DocumentStatus.Reason.Length > 50)
            {
                erro = new Error { Description = string.Format("Tamanho do motivo da alteração de estado do recibo {0} incorrecto.", this.PaymentRefNo), Field = "Reason", TypeofError = this.GetType(), Value = this.DocumentStatus.Reason, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Reason = this.Tooltip.Reason.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateDocumentStatusSourceID(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.DocumentStatus.SourceID) || this.DocumentStatus.SourceID.Length > 30)
            {
                erro = new Error { Description = string.Format("Utilizador responsável pelo estado atual do recibo {0} incorrecto.", this.DocumentStatus.SourceID), Field = "SourceID", TypeofError = this.GetType(), Value = this.DocumentStatus.SourceID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.ResponsableUserSourceID = this.Tooltip.ResponsableUserSourceID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateSystemID(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.SystemID) == false && this.SystemID.Length > 35)
            {
                erro = new Error { Description = string.Format("Tamanho do número único do recibo {0} incorrecto.", this.PaymentRefNo), Field = "SystemID", TypeofError = this.GetType(), Value = this.SystemID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.SystemID = this.Tooltip.SystemID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateSourceID(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.SourceID) || this.SourceID.Length > 30)
            {
                erro = new Error { Description = string.Format("Utilizador que gerou o documento {0} incorrecto.", this.SourceID), Field = "SourceID", TypeofError = this.GetType(), Value = this.SourceID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.GeneratedDocumentUserSourceID = this.Tooltip.GeneratedDocumentUserSourceID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateSystemEntryDate(bool appendError = false)
        {
            Error erro = null;

            if (this.SystemEntryDate < Workspace.Instance.Config.MinDate || this.SystemEntryDate > DateTime.Now)
            {
                erro = new Error { Description = string.Format("Data da gravação do documento {0} incorrecta.", this.PaymentRefNo), Field = "SystemEntryDate", TypeofError = this.GetType(), Value = this.SystemEntryDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.SystemEntryDate = this.Tooltip.SystemEntryDate.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateCustomerID(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.CustomerID) || this.CustomerID.Length > 30)
            {
                erro = new Error { Description = string.Format("Chave única da tabela de clientes no documento {0} incorrecta.", this.PaymentRefNo), Field = "CustomerID", TypeofError = this.GetType(), Value = this.CustomerID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.CustomerID = this.Tooltip.CustomerID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }

        public Error[] ValidatePaymentMethod(bool appendError = false)
        {
            List<Error> listErro = new List<Error>();

            if (this.PaymentMethod != null && this.PaymentMethod.Length > 0)
            {
                foreach (var pay in this.PaymentMethod)
                {
                    if (pay.PaymentAmount < 0)
                    {
                        Error erro = new Error { Description = string.Format("Utilizador que gerou o documento {0} incorrecto.", this.PaymentRefNo), Field = "PaymentAmount", TypeofError = this.GetType(), Value = pay.PaymentAmount.ToString(), UID = this.Pk };
                        listErro.Add(erro);
                        if (appendError)
                            this.Tooltip.PaymentMechanism = this.Tooltip.PaymentMechanism.FormatTooltipWithError(erro.Description);
                    }

                    if (pay.PaymentDate < Workspace.Instance.Config.MinDate || pay.PaymentDate > DateTime.Now)
                    {
                        Error erro = new Error { Description = string.Format("Data do pagamento do documento {0} incorrecta.", this.PaymentRefNo), Field = "PaymentDate", TypeofError = this.GetType(), Value = pay.PaymentDate.ToString(), UID = this.Pk };
                        listErro.Add(erro);
                        if (appendError)
                            this.Tooltip.PaymentMechanism = this.Tooltip.PaymentMechanism.FormatTooltipWithError(erro.Description);
                    }
                }
            }
            return listErro.ToArray();
        }
        #endregion
    }

    public partial class SourceDocumentsPaymentsPaymentLine : BaseData, IDataErrorInfo
    {
        /// <summary>
        /// Link to the Payment
        /// </summary>
        public string DocNo { get; set; }

        SourceDocumentsPaymentsPaymentLineToolTipService tooltip;
        public SourceDocumentsPaymentsPaymentLineToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new SourceDocumentsPaymentsPaymentLineToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        [System.Runtime.CompilerServices.IndexerName("Items")]
        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "LineNumber")
                {
                    erro = ValidateLineNumber(appendError: true);
                }
                else if (columnName == "SettlementAmount")
                {
                    erro = ValidateSettlementAmount(appendError: true);
                }
                else if (columnName == "TaxExemptionReason")
                {
                    erro = ValidateTaxExemptionReason(appendError: true);
                }
                else if (columnName == "Item")
                {
                    erro = ValidateItem(appendError: true);
                }

                return erro == null ? erro.Description : null;
            }
        }

        #region
        public Error ValidateLineNumber(bool appendError = false, string SupPk = "", string paymentNo = "")
        {
            Error erro = null;
            int num = -1;
            if (!string.IsNullOrEmpty(this.LineNumber))
                Int32.TryParse(this.LineNumber, out num);

            if (string.IsNullOrEmpty(this.LineNumber) || num == -1)
            {
                if (!string.IsNullOrEmpty(paymentNo))
                    paymentNo = string.Format(", documento {0}", paymentNo);

                erro = new Error { Description = string.Format("Número de linha incorrecto{0}.", paymentNo), Field = "LineNumber", TypeofError = this.GetType(), Value = this.LineNumber, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.LineNumber = this.Tooltip.LineNumber.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateSettlementAmount(bool appendError = false, string SupPk = "", string paymentNo = "")
        {
            Error erro = null;
            if (this.SettlementAmount < 0)
            {
                if (!string.IsNullOrEmpty(paymentNo))
                    paymentNo = string.Format(" documento {0}", paymentNo);

                erro = new Error { Description = string.Format("Montante do desconto, {0} linha {1}.", paymentNo, this.LineNumber), Field = "SettlementAmount", TypeofError = this.GetType(), Value = this.SettlementAmount.ToString(), UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.LineSettlementAmount = this.Tooltip.LineSettlementAmount.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateItem(bool appendError = false, string SupPk = "", string paymentNo = "")
        {
            Error erro = null;
            if (this.Item < 0)
            {
                if (!string.IsNullOrEmpty(paymentNo))
                    paymentNo = string.Format(" documento {0}", paymentNo);

                if (this.ItemElementName == ItemChoiceType9.CreditAmount)
                    erro = new Error { Description = string.Format("Valor a crédito incorrecta, {0} linha {1}.", paymentNo, this.LineNumber), Field = "CreditAmount", TypeofError = this.GetType(), Value = this.Item.ToString(), UID = this.Pk, SupUID = SupPk };
                if (this.ItemElementName == ItemChoiceType9.DebitAmount)
                    erro = new Error { Description = string.Format("Valor a débito incorrecto, {0} linha {1}.", paymentNo, this.LineNumber), Field = "DebitAmount", TypeofError = this.GetType(), Value = this.Item.ToString(), UID = this.Pk, SupUID = SupPk };

                if (appendError && this.ItemElementName == ItemChoiceType9.CreditAmount)
                    this.Tooltip.CreditAmount = this.Tooltip.CreditAmount.FormatTooltipWithError(erro.Description);
                if (appendError && this.ItemElementName == ItemChoiceType9.DebitAmount)
                    this.Tooltip.DebitAmount = this.Tooltip.DebitAmount.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateTaxExemptionReason(bool appendError = false, string SupPk = "", string paymentNo = "")
        {
            Error erro = null;
            if ((this.Tax != null && this.Tax.Item == 0 && string.IsNullOrEmpty(this.TaxExemptionReason)) || (string.IsNullOrEmpty(this.TaxExemptionReason) == false && this.TaxExemptionReason.Length > 60))
            {
                if (!string.IsNullOrEmpty(paymentNo))
                    paymentNo = string.Format(" documento {0}", paymentNo);

                erro = new Error { Description = string.Format("Motivo da isenção de imposto incorrecto, {0} linha {1}.", paymentNo, this.LineNumber), Field = "TaxExemptionReason", TypeofError = this.GetType(), Value = this.TaxExemptionReason, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.TaxExemptionReason = this.Tooltip.TaxExemptionReason.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }

        public Error[] ValidateSourceDocumentID(string SupPk = "", string paymentNo = "")
        {
            List<Error> listErro = new List<Error>();

            if (!string.IsNullOrEmpty(paymentNo))
                paymentNo = string.Format(" documento {0}", paymentNo);

            if (this.SourceDocumentID == null || this.SourceDocumentID.Length == 0)
                listErro.Add(new Error { Description = string.Format("Referência ao documento de origem inexistente,{0} linha {1}.", paymentNo, this.LineNumber), Field = "SourceDocumentID", TypeofError = this.GetType(), UID = this.Pk, SupUID = SupPk });

            if (this.SourceDocumentID != null && this.SourceDocumentID.Length > 0)
            {
                foreach (var doc in this.SourceDocumentID)
                {
                    if (string.IsNullOrEmpty(doc.Description) == false && doc.Description.Length > 100)
                        listErro.Add(new Error { Description = string.Format("Tamanho da descrição da linha incorrecto,{0} linha {1}.", paymentNo, this.LineNumber), Field = "Description", TypeofError = this.GetType(), Value = doc.Description, UID = this.Pk, SupUID = SupPk });
                    if (doc.InvoiceDate < Workspace.Instance.Config.MinDate || doc.InvoiceDate > DateTime.Now)
                        listErro.Add(new Error { Description = string.Format("Data do documento de origem incorrecta,{0} linha {1}.", paymentNo, this.LineNumber), Field = "InvoiceDate", TypeofError = this.GetType(), Value = doc.InvoiceDate.ToString(), UID = this.Pk, SupUID = SupPk });
                    if (string.IsNullOrEmpty(doc.OriginatingON) || doc.OriginatingON.Length > 60)
                        listErro.Add(new Error { Description = string.Format("Número do documento de origem incorrecto,{0} linha {1}.", paymentNo, this.LineNumber), Field = "OriginatingON", TypeofError = this.GetType(), Value = doc.OriginatingON, UID = this.Pk, SupUID = SupPk });
                }
            }
            return listErro.ToArray();
        }
        public Error[] ValidateTax(string SupPk = "", string paymentNo = "")
        {
            List<Error> listErro = new List<Error>();
            if (this.Tax != null)
            {
                if (!string.IsNullOrEmpty(paymentNo))
                    paymentNo = string.Format(" documento {0}", paymentNo);

                if (this.Tax.Item < 0 && this.Tax.ItemElementName == ItemChoiceType.TaxAmount)
                    listErro.Add(new Error { Description = string.Format("Montante do imposto incorrecto, {0} linha {1}.", paymentNo, this.LineNumber), Field = "TaxAmount", TypeofError = this.GetType(), Value = this.Tax.Item.ToString(), UID = this.Pk, SupUID = SupPk });
                if ((this.Tax.Item < 0 || this.Tax.Item > 100) && this.Tax.ItemElementName == ItemChoiceType.TaxPercentage)
                    listErro.Add(new Error { Description = string.Format("Montante do imposto incorrecto, {0} linha {1}.", paymentNo, this.LineNumber), Field = "TaxPercentage", TypeofError = this.GetType(), Value = this.Tax.Item.ToString(), UID = this.Pk, SupUID = SupPk });
                if (string.IsNullOrEmpty(this.Tax.TaxCode) || this.Tax.TaxCode.Length > 10)
                    listErro.Add(new Error { Description = string.Format("Código da taxa incorrecto, {0} linha {1}.", paymentNo, this.LineNumber), Field = "TaxCode", TypeofError = this.GetType(), Value = this.Tax.TaxCode, UID = this.Pk, SupUID = SupPk });
                if (string.IsNullOrEmpty(this.Tax.TaxCountryRegion) || this.Tax.TaxCode.Length > 5)
                    listErro.Add(new Error { Description = string.Format("País ou região do imposto incorrecto, {0} linha {1}.", paymentNo, this.LineNumber), Field = "TaxCountryRegion", TypeofError = this.GetType(), Value = this.Tax.TaxCountryRegion, UID = this.Pk, SupUID = SupPk });
            }
            return listErro.ToArray();
        }
        #endregion
    }

    public partial class SourceDocumentsMovementOfGoodsStockMovement : BaseData, IDataErrorInfo
    {
        public string HashTest { get; set; }

        MovementOfGoodsToolTipService tooltip;
        public MovementOfGoodsToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new MovementOfGoodsToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get
            {
                StringBuilder error = new StringBuilder();

                // iterate over all of the properties
                // of this object - aggregating any validation errors
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this);
                foreach (PropertyDescriptor prop in props)
                {
                    String propertyError = this[prop.Name];
                    if (propertyError != string.Empty)
                        error.Append((error.Length != 0 ? ", " : "") + propertyError);
                }

                return error.Length == 0 ? null : error.ToString();
            }
        }

        [System.Runtime.CompilerServices.IndexerName("Items")]
        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "DocumentNumber")
                {
                    erro = ValidateDocumentNumber(appendError: true);
                }
                else if (columnName == "Hash")
                {
                    erro = ValidateHash(appendError: true);
                }
                else if (columnName == "HashControl")
                {
                    erro = ValidateHashControl(appendError: true);
                }
                else if (columnName == "Period")
                {
                    erro = ValidatePeriod(appendError: true);
                }
                else if (columnName == "MovementDate")
                {
                    erro = ValidateMovementDate(appendError: true);
                }
                else if (columnName == "SystemEntryDate")
                {
                    erro = ValidateSystemEntryDate(appendError: true);
                }
                else if (columnName == "TransactionID")
                {
                    erro = ValidateTransactionID(appendError: true);
                }
                else if (columnName == "MovementEndTime")
                {
                    erro = ValidateMovementEndTime(appendError: true);
                }
                else if (columnName == "MovementStartTime")
                {
                    erro = ValidateMovementStartTime(appendError: true);
                }
                return erro == null ? erro.Description : null;
            }
        }

        #region Validation
        public Error ValidateDocumentNumber(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.DocumentNumber) || this.DocumentNumber.Length > 60)
            {
                erro = new Error { Description = "Identificação única com tamanho incorrecto.", Field = "DocumentNumber", TypeofError = this.GetType(), Value = this.DocumentNumber, UID = this.Pk };
                if (appendError)
                    this.Tooltip.DocumentNumber = this.Tooltip.DocumentNumber.FormatTooltipWithError(erro.Description);
            }
            else if (!Regex.IsMatch(this.DocumentNumber, "([a-zA-Z0-9./_-])+ ([a-zA-Z0-9]*/[0-9]+)"))
            {
                erro = new Error { Description = "Identificação única com caracteres não permitidos.", Field = "DocumentNumber", TypeofError = this.GetType(), Value = this.DocumentNumber, UID = this.Pk };
                if (appendError)
                    this.Tooltip.DocumentNumber = this.Tooltip.DocumentNumber.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateHash(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.Hash) || this.Hash.Length != 172)
            {
                erro = new Error { Description = string.Format("Assinatura do documento {0} de tamanho incorrecto.", this.DocumentNumber), Field = "Hash", TypeofError = this.GetType(), Value = this.Hash, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Hash = this.Tooltip.Hash.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateHashControl(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.HashControl) || this.HashControl.Length > 40)
            {
                erro = new Error { Description = string.Format("Versão da chave privada utilizada na assinatura do documento {0} incorrecta.", this.DocumentNumber), Field = "HashControl", TypeofError = this.GetType(), Value = this.HashControl, UID = this.Pk };
                if (appendError)
                    this.Tooltip.HashControl = this.Tooltip.HashControl.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidatePeriod(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.Period) == false)
            {
                int periodo = -1;
                Int32.TryParse(this.Period, out periodo);

                if (periodo < 1 || periodo > 12)
                {
                    erro = new Error { Description = string.Format("Mês do período de tributação do documento {0} incorrecto.", this.DocumentNumber), Field = "Period", TypeofError = this.GetType(), Value = this.Period, UID = this.Pk };
                    if (appendError)
                        this.Tooltip.Period = this.Tooltip.Period.FormatTooltipWithError(erro.Description);
                }
            }

            return erro;
        }
        public Error ValidateMovementDate(bool appendError = false)
        {
            Error erro = null;

            if (this.MovementDate < Workspace.Instance.Config.MinDate || this.MovementDate > DateTime.Now)
            {
                erro = new Error { Description = string.Format("Data de emissão do documento {0} incorrecta.", this.DocumentNumber), Field = "InvoiceDate", TypeofError = this.GetType(), Value = this.MovementDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.MovementDate = this.Tooltip.MovementDate.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateSystemEntryDate(bool appendError = false)
        {
            Error erro = null;

            if (this.SystemEntryDate < Workspace.Instance.Config.MinDate || this.SystemEntryDate > DateTime.Now)
            {
                erro = new Error { Description = string.Format("Data da gravação do documento {0} incorrecta.", this.DocumentNumber), Field = "SystemEntryDate", TypeofError = this.GetType(), Value = this.SystemEntryDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.SystemEntryDate = this.Tooltip.SystemEntryDate.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateTransactionID(bool appendError = false)
        {
            Error erro = null;

            if (!string.IsNullOrEmpty(this.TransactionID) && this.TransactionID.Length > 70)
            {
                erro = new Error { Description = string.Format("Identificador da transacção do documento {0} incorrecto.", this.DocumentNumber), Field = "TransactionID", TypeofError = this.GetType(), Value = this.TransactionID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.TransactionID = this.Tooltip.TransactionID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateMovementEndTime(bool appendError = false)
        {
            Error erro = null;

            if (this.MovementEndTimeSpecified && (this.MovementEndTime < Workspace.Instance.Config.MinDate || this.MovementEndTime > DateTime.Now))
            {
                erro = new Error { Description = string.Format("Data e hora de fim de transporte do documento {0} incorrecta.", this.DocumentNumber), Field = "MovementEndTime", TypeofError = this.GetType(), Value = this.MovementEndTime.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.MovementEndTime = this.Tooltip.MovementEndTime.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateMovementStartTime(bool appendError = false)
        {
            Error erro = null;

            if (this.MovementStartTime < Workspace.Instance.Config.MinDate || this.MovementStartTime > DateTime.Now)
            {
                erro = new Error { Description = string.Format("Data e hora de início de transporte do documento {0} incorrecta.", this.DocumentNumber), Field = "MovementStartTime", TypeofError = this.GetType(), Value = this.MovementStartTime.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.MovementStartTime = this.Tooltip.MovementStartTime.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }

        public Error[] ValidateDocumentStatus()
        {
            List<Error> listError = new List<Error>();

            if (this.DocumentStatus == null)
                listError.Add(new Error { Description = string.Format("Situação do documento {0} inexistente.", this.DocumentNumber), Field = "DocumentStatus", TypeofError = this.GetType(), UID = this.Pk });

            if (this.DocumentStatus != null)
            {
                if (this.DocumentStatus.MovementStatusDate < Workspace.Instance.Config.MinDate || this.DocumentStatus.MovementStatusDate > DateTime.Now)
                    listError.Add(new Error { Description = string.Format("Data e hora do estado atual do documento {0} incorrecta.", this.DocumentNumber), Field = "InvoiceStatusDate", TypeofError = this.GetType(), Value = this.DocumentStatus.MovementStatusDate.ToString(), UID = this.Pk });
                if (string.IsNullOrEmpty(this.DocumentStatus.Reason) == false && this.DocumentStatus.Reason.Length > 50)
                    listError.Add(new Error { Description = string.Format("Tamanho do motivo da alteração de estado {0} incorrecto.", this.DocumentNumber), Field = "Reason", TypeofError = this.GetType(), Value = this.DocumentStatus.Reason, UID = this.Pk });
                if (string.IsNullOrEmpty(this.DocumentStatus.SourceID) || this.DocumentStatus.SourceID.Length > 30)
                    listError.Add(new Error { Description = string.Format("Utilizador responsável pelo estado atual do documento {0} incorrecto.", this.DocumentNumber), Field = "SourceID", TypeofError = this.GetType(), Value = this.DocumentStatus.SourceID, UID = this.Pk });
            }

            return listError.ToArray();
        }
        public Error[] ValidateShipTo()
        {
            List<Error> listError = new List<Error>();

            if (this.ShipTo != null)
            {
                if (this.ShipTo.Address != null)
                {
                    if (string.IsNullOrEmpty(this.ShipTo.Address.AddressDetail) || this.ShipTo.Address.AddressDetail.Length > 100)
                        listError.Add(new Error { Description = string.Format("Tamanho da morada detalhada do documento {0} do local de descarga incorrecto.", this.DocumentNumber), Field = "AddressDetail", TypeofError = this.GetType(), Value = this.ShipTo.Address.AddressDetail, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.BuildingNumber) == false && this.ShipTo.Address.BuildingNumber.Length > 10)
                        listError.Add(new Error { Description = string.Format("Tamanho do número de polícia do documento {0} do local de descarga incorrecto.", this.DocumentNumber), Field = "BuildingNumber", TypeofError = this.GetType(), Value = this.ShipTo.Address.BuildingNumber, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.City) || this.ShipTo.Address.City.Length > 50)
                        listError.Add(new Error { Description = string.Format("Tamanho da localidade do documento {0} do local de descarga incorrecto.", this.DocumentNumber), Field = "City", TypeofError = this.GetType(), Value = this.ShipTo.Address.City, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.Country) || this.ShipTo.Address.Country.Length != 2)
                        listError.Add(new Error { Description = string.Format("Tamanho do País do documento {0} do local de descarga incorrecto.", this.DocumentNumber), Field = "Country", TypeofError = this.GetType(), Value = this.ShipTo.Address.Country, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.PostalCode) || this.ShipTo.Address.PostalCode.Length > 20)
                        listError.Add(new Error { Description = string.Format("Tamanho do código postal do documento {0} do local de descarga incorrecto.", this.DocumentNumber), Field = "PostalCode", TypeofError = this.GetType(), Value = this.ShipTo.Address.PostalCode, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.Region) == false && this.ShipTo.Address.Region.Length > 50)
                        listError.Add(new Error { Description = string.Format("Tamanho do distrito do documento {0} do local de descarga incorrecto.", this.DocumentNumber), Field = "Region", TypeofError = this.GetType(), Value = this.ShipTo.Address.Region, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.StreetName) == false && this.ShipTo.Address.StreetName.Length > 90)
                        listError.Add(new Error { Description = string.Format("Tamanho do nome da rua do documento {0} do local de descarga incorrecto.", this.DocumentNumber), Field = "StreetName", TypeofError = this.GetType(), Value = this.ShipTo.Address.StreetName, UID = this.Pk });
                }
                if (this.ShipTo.DeliveryDate < Workspace.Instance.Config.MinDate || this.ShipTo.DeliveryDate > DateTime.Now)
                    listError.Add(new Error { Description = string.Format("Data da entrega do documento {0} incorrecto.", this.DocumentNumber), Field = "DeliveryDate", TypeofError = this.GetType(), Value = this.ShipTo.DeliveryDate.ToString(), UID = this.Pk });
            }

            return listError.ToArray();
        }
        public Error[] ValidateShipFrom()
        {
            List<Error> listError = new List<Error>();

            if (this.ShipFrom != null)
            {
                if (this.ShipFrom.Address != null)
                {
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.AddressDetail) || this.ShipFrom.Address.AddressDetail.Length > 100)
                        listError.Add(new Error { Description = string.Format("Tamanho da morada detalhada do documento {0} do local de carga incorrecto.", this.DocumentNumber), Field = "AddressDetail", TypeofError = this.GetType(), Value = this.ShipFrom.Address.AddressDetail, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.BuildingNumber) == false && this.ShipFrom.Address.BuildingNumber.Length > 10)
                        listError.Add(new Error { Description = string.Format("Tamanho do número de polícia do documento {0} do local de carga incorrecto.", this.DocumentNumber), Field = "BuildingNumber", TypeofError = this.GetType(), Value = this.ShipFrom.Address.BuildingNumber, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.City) || this.ShipFrom.Address.City.Length > 50)
                        listError.Add(new Error { Description = string.Format("Tamanho da localidade do documento {0} do local de carga incorrecto.", this.DocumentNumber), Field = "City", TypeofError = this.GetType(), Value = this.ShipFrom.Address.City, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.Country) || this.ShipFrom.Address.Country.Length != 2)
                        listError.Add(new Error { Description = string.Format("Tamanho do País do documento {0} do local de carga incorrecto.", this.DocumentNumber), Field = "Country", TypeofError = this.GetType(), Value = this.ShipFrom.Address.Country, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.PostalCode) || this.ShipFrom.Address.PostalCode.Length > 20)
                        listError.Add(new Error { Description = string.Format("Tamanho do código postal do documento {0} do local de carga incorrecto.", this.DocumentNumber), Field = "PostalCode", TypeofError = this.GetType(), Value = this.ShipFrom.Address.PostalCode, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.Region) == false && this.ShipFrom.Address.Region.Length > 50)
                        listError.Add(new Error { Description = string.Format("Tamanho do distrito do documento {0} do local de carga incorrecto.", this.DocumentNumber), Field = "Region", TypeofError = this.GetType(), Value = this.ShipFrom.Address.Region, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.StreetName) == false && this.ShipFrom.Address.StreetName.Length > 90)
                        listError.Add(new Error { Description = string.Format("Tamanho do nome da rua do documento {0} do local de carga incorrecto.", this.DocumentNumber), Field = "StreetName", TypeofError = this.GetType(), Value = this.ShipFrom.Address.StreetName, UID = this.Pk });
                }
                if (this.ShipFrom.DeliveryDate < Workspace.Instance.Config.MinDate || this.ShipFrom.DeliveryDate > DateTime.Now)
                    listError.Add(new Error { Description = string.Format("Data da receção do documento {0} incorrecto.", this.DocumentNumber), Field = "DeliveryDate", TypeofError = this.GetType(), Value = this.ShipFrom.DeliveryDate.ToString(), UID = this.Pk });
            }

            return listError.ToArray();
        }
        public Error[] ValidateDocumentTotals()
        {
            List<Error> listError = new List<Error>();

            if (this.DocumentTotals == null)
                listError.Add(new Error { Description = string.Format("Totais do documento {0} inexistentes.", this.DocumentNumber), Field = "DocumentTotals", TypeofError = this.GetType(), UID = this.Pk });

            if (this.DocumentTotals != null)
            {
                if (this.DocumentTotals.Currency != null)
                {
                    if (this.DocumentTotals.Currency.CurrencyAmount < 0)
                        listError.Add(new Error { Description = string.Format("Valor total em moeda estrangeira do documento {0} incorrecto.", this.DocumentNumber), Field = "CurrencyAmount", TypeofError = this.GetType(), Value = this.DocumentTotals.Currency.CurrencyAmount.ToString(), UID = this.Pk });
                    if (string.IsNullOrEmpty(this.DocumentTotals.Currency.CurrencyCode) || this.DocumentTotals.Currency.CurrencyCode.Length > 3)
                        listError.Add(new Error { Description = string.Format("Tamanho do código de moeda do documento {0} incorrecto.", this.DocumentNumber), Field = "CurrencyCode", TypeofError = this.GetType(), Value = this.DocumentTotals.Currency.CurrencyCode, UID = this.Pk });
                    if (this.DocumentTotals.Currency.ExchangeRateSpecified && this.DocumentTotals.Currency.ExchangeRate < 0)
                        listError.Add(new Error { Description = string.Format("Taxa de câmbio do documento {0} incorrecta.", this.DocumentNumber), Field = "ExchangeRate", TypeofError = this.GetType(), Value = this.DocumentTotals.Currency.ExchangeRate.ToString(), UID = this.Pk });
                }

                if (this.DocumentTotals.GrossTotal < 0)
                    listError.Add(new Error { Description = string.Format("Total do documento {0} incorrecto.", this.DocumentNumber), Field = "GrossTotal", TypeofError = this.GetType(), Value = this.DocumentTotals.GrossTotal.ToString(), UID = this.Pk });
                if (this.DocumentTotals.NetTotal < 0)
                    listError.Add(new Error { Description = string.Format("Total do documento {0} sem impostos incorrecto.", this.DocumentNumber), Field = "NetTotal", TypeofError = this.GetType(), Value = this.DocumentTotals.NetTotal.ToString(), UID = this.Pk });
                if (this.DocumentTotals.TaxPayable < 0)
                    listError.Add(new Error { Description = string.Format("Valor do imposto a pagar do documento {0} incorrecto.", this.DocumentNumber), Field = "TaxPayable", TypeofError = this.GetType(), Value = this.DocumentTotals.TaxPayable.ToString(), UID = this.Pk });
            }

            return listError.ToArray();
        }
        #endregion
    }

    public partial class SourceDocumentsMovementOfGoodsStockMovementLine : BaseData, IDataErrorInfo
    {
        /// <summary>
        /// Link to the doc
        /// </summary>
        public string DocNo { get; set; }

        MovementOfGoodsLineToolTipService tooltip;
        public MovementOfGoodsLineToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new MovementOfGoodsLineToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get
            {
                StringBuilder error = new StringBuilder();

                // iterate over all of the properties
                // of this object - aggregating any validation errors
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this);
                foreach (PropertyDescriptor prop in props)
                {
                    String propertyError = this[prop.Name];
                    if (propertyError != string.Empty)
                        error.Append((error.Length != 0 ? ", " : "") + propertyError);
                }

                return error.Length == 0 ? null : error.ToString();
            }
        }

        [System.Runtime.CompilerServices.IndexerName("Items")]
        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "LineNumber")
                {
                    erro = ValidateLineNumber(appendError: true);
                }
                else if (columnName == "ProductCode")
                {
                    erro = ValidateProductCode(appendError: true);
                }
                else if (columnName == "ProductDescription")
                {
                    erro = ValidateProductDescription(appendError: true);
                }
                else if (columnName == "Quantity")
                {
                    erro = ValidateQuantity(appendError: true);
                }
                else if (columnName == "UnitOfMeasure")
                {
                    erro = ValidateUnitOfMeasure(appendError: true);
                }
                else if (columnName == "UnitPrice")
                {
                    erro = ValidateUnitPrice(appendError: true);
                }
                return erro == null ? erro.Description : null;
            }
        }

        public Error ValidateLineNumber(bool appendError = false, string SupPk = "", string movement = "")
        {
            Error erro = null;
            int num = -1;
            if (!string.IsNullOrEmpty(this.LineNumber))
                Int32.TryParse(this.LineNumber, out num);

            if (string.IsNullOrEmpty(this.LineNumber) || num == -1)
            {
                if (!string.IsNullOrEmpty(movement))
                    movement = string.Format(", documento {0}", movement);

                erro = new Error { Description = string.Format("Número de linha incorrecto {0}.", movement), Field = "LineNumber", TypeofError = this.GetType(), Value = this.LineNumber, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.LineNumber = this.Tooltip.LineNumber.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateProductCode(bool appendError = false, string SupPk = "", string movement = "")
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductCode) || this.ProductCode.Length > 30)
            {
                if (!string.IsNullOrEmpty(movement))
                    movement = string.Format(" documento {0}", movement);

                erro = new Error { Description = string.Format("Identificador do produto ou serviço incorrecto, {0} linha {1}.", movement, this.LineNumber), Field = "ProductCode", TypeofError = this.GetType(), Value = this.ProductCode, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.ProductCode = this.Tooltip.ProductCode.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateProductDescription(bool appendError = false, string SupPk = "", string movement = "")
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductDescription) || this.ProductDescription.Length > 200)
            {
                if (!string.IsNullOrEmpty(movement))
                    movement = string.Format(" documento {0}", movement);

                erro = new Error { Description = string.Format("Descrição do produto ou serviço incorrecta, {0} linha {1}.", movement, this.LineNumber), Field = "ProductDescription", TypeofError = this.GetType(), Value = this.ProductDescription, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.ProductDescription = this.Tooltip.ProductDescription.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateQuantity(bool appendError = false, string SupPk = "", string movement = "")
        {
            Error erro = null;
            if (this.Quantity <= 0)
            {
                if (!string.IsNullOrEmpty(movement))
                    movement = string.Format(" documento {0}", movement);

                erro = new Error { Description = string.Format("Quantidade incorrecta, {0} linha {1}.", movement, this.LineNumber), Field = "Quantity", TypeofError = this.GetType(), Value = this.Quantity.ToString(), UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.Quantity = this.Tooltip.Quantity.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateUnitOfMeasure(bool appendError = false, string SupPk = "", string movement = "")
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.UnitOfMeasure) || this.UnitOfMeasure.Length > 20)
            {
                if (!string.IsNullOrEmpty(movement))
                    movement = string.Format(" documento {0}", movement);

                erro = new Error { Description = string.Format("Unidade de medida incorrecta, {0} linha {1}.", movement, this.LineNumber), Field = "UnitOfMeasure", TypeofError = this.GetType(), Value = this.UnitOfMeasure, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.UnitOfMeasure = this.Tooltip.UnitOfMeasure.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateUnitPrice(bool appendError = false, string SupPk = "", string movement = "")
        {
            Error erro = null;
            if (this.UnitPrice == 0)
            {
                if (!string.IsNullOrEmpty(movement))
                    movement = string.Format(" documento {0}", movement);

                erro = new Error { Description = string.Format("Preço unitário incorrecto, {0} linha {1}.", movement, this.LineNumber), Field = "UnitPrice", TypeofError = this.GetType(), Value = this.UnitPrice.ToString(), UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.UnitPrice = this.Tooltip.UnitPrice.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }

        public Error[] ValidateOrderReferences(string SupPk = "", string movement = "")
        {
            List<Error> listError = new List<Error>();

            if (this.OrderReferences != null && this.OrderReferences.Length > 0)
            {
                foreach (var referencia in this.OrderReferences)
                {
                    if (string.IsNullOrEmpty(referencia.OriginatingON) == false && referencia.OriginatingON.Length > 60)
                        listError.Add(new Error { Description = string.Format("Tamanho do número do documento de origem na linha {0} do documento {1} incorrecto.", this.LineNumber, movement), Field = "OriginatingON", TypeofError = this.GetType(), Value = referencia.OriginatingON, UID = this.Pk, SupUID = SupPk });
                    if (referencia.OrderDateSpecified && (referencia.OrderDate < Workspace.Instance.Config.MinDate || referencia.OrderDate > DateTime.Now))
                        listError.Add(new Error { Description = string.Format("Data do documento de origem na linha {0} do documento {1} incorrecto.", this.LineNumber, movement), Field = "OrderDate", TypeofError = this.GetType(), Value = referencia.OrderDate.ToString(), UID = this.Pk, SupUID = SupPk });
                }
            }

            return listError.ToArray();
        }
        public Error[] ValidateTax(string SupPk = "", string movement = "")
        {
            List<Error> listError = new List<Error>();

            if (this.Tax == null)
                listError.Add(new Error { Description = string.Format("Taxa de imposto na linha {0} do documento {1} inexistente.", this.LineNumber, movement), Field = "Tax", TypeofError = this.GetType(), UID = this.Pk, SupUID = SupPk });

            if (this.Tax != null)
            {
                if (this.Tax.TaxPercentage < 0 || this.Tax.TaxPercentage > 100)
                    listError.Add(new Error { Description = string.Format("Percentagem da taxa do imposto na linha {0} do documento {1} incorrecto.", this.LineNumber, movement), Field = "TaxPercentage", TypeofError = this.GetType(), Value = this.Tax.TaxPercentage.ToString(), UID = this.Pk, SupUID = SupPk });
                if (string.IsNullOrEmpty(this.Tax.TaxCode) || this.Tax.TaxCode.Length > 10)
                    listError.Add(new Error { Description = string.Format("Código da taxa na linha {0} do documento {1} incorrecto.", this.LineNumber, movement), Field = "TaxCode", TypeofError = this.GetType(), Value = this.Tax.TaxCode, UID = this.Pk, SupUID = SupPk });
                if (string.IsNullOrEmpty(this.Tax.TaxCountryRegion) || this.Tax.TaxCountryRegion.Length > 5)
                    listError.Add(new Error { Description = string.Format("País ou região do imposto na linha {0} do documento {1} incorrecto.", this.LineNumber, movement), Field = "TaxCountryRegion", TypeofError = this.GetType(), Value = this.Tax.TaxCountryRegion, UID = this.Pk, SupUID = SupPk });
            }

            return listError.ToArray();
        }
    }

    public partial class SourceDocumentsWorkingDocumentsWorkDocument : BaseData, IDataErrorInfo
    {
        public string HashTest { get; set; }

        WorkingDocumentsToolTipService tooltip;
        public WorkingDocumentsToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new WorkingDocumentsToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get
            {
                StringBuilder error = new StringBuilder();

                // iterate over all of the properties
                // of this object - aggregating any validation errors
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this);
                foreach (PropertyDescriptor prop in props)
                {
                    String propertyError = this[prop.Name];
                    if (propertyError != string.Empty)
                        error.Append((error.Length != 0 ? ", " : "") + propertyError);
                }

                return error.Length == 0 ? null : error.ToString();
            }
        }

        [System.Runtime.CompilerServices.IndexerName("Items")]
        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "DocumentNumber")
                {
                    erro = ValidateDocumentNumber(appendError: true);
                }
                else if (columnName == "Hash")
                {
                    erro = ValidateHash(appendError: true);
                }
                else if (columnName == "HashControl")
                {
                    erro = ValidateHashControl(appendError: true);
                }
                else if (columnName == "Period")
                {
                    erro = ValidatePeriod(appendError: true);
                }
                else if (columnName == "WorkDate")
                {
                    erro = ValidateWorkDate(appendError: true);
                }
                else if (columnName == "SystemEntryDate")
                {
                    erro = ValidateSystemEntryDate(appendError: true);
                }
                return erro == null ? erro.Description : null;
            }
        }

        #region Validation
        public Error ValidateDocumentNumber(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.DocumentNumber) || this.DocumentNumber.Length > 60)
            {
                erro = new Error { Description = "Identificação única com tamanho incorrecto.", Field = "DocumentNumber", TypeofError = this.GetType(), Value = this.DocumentNumber, UID = this.Pk };
                if (appendError)
                    this.Tooltip.DocumentNumber = this.Tooltip.DocumentNumber.FormatTooltipWithError(erro.Description);
            }
            else if (!Regex.IsMatch(this.DocumentNumber, "([a-zA-Z0-9./_-])+ ([a-zA-Z0-9]*/[0-9]+)"))
            {
                erro = new Error { Description = "Identificação única com caracteres não permitidos.", Field = "DocumentNumber", TypeofError = this.GetType(), Value = this.DocumentNumber, UID = this.Pk };
                if (appendError)
                    this.Tooltip.DocumentNumber = this.Tooltip.DocumentNumber.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateHash(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.Hash) || this.Hash.Length != 172)
            {
                erro = new Error { Description = string.Format("Assinatura do documento {0} de tamanho incorrecto.", this.DocumentNumber), Field = "Hash", TypeofError = this.GetType(), Value = this.Hash, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Hash = this.Tooltip.Hash.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateHashControl(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.HashControl) || this.HashControl.Length > 40)
            {
                erro = new Error { Description = string.Format("Versão da chave privada utilizada na assinatura do documento {0} incorrecta.", this.DocumentNumber), Field = "HashControl", TypeofError = this.GetType(), Value = this.HashControl, UID = this.Pk };
                if (appendError)
                    this.Tooltip.HashControl = this.Tooltip.HashControl.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidatePeriod(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.Period) == false)
            {
                int periodo = -1;
                Int32.TryParse(this.Period, out periodo);

                if (periodo < 1 || periodo > 12)
                {
                    erro = new Error { Description = string.Format("Mês do período de tributação do documento {0} incorrecto.", this.DocumentNumber), Field = "Period", TypeofError = this.GetType(), Value = this.Period, UID = this.Pk };
                    if (appendError)
                        this.Tooltip.Period = this.Tooltip.Period.FormatTooltipWithError(erro.Description);
                }
            }

            return erro;
        }
        public Error ValidateWorkDate(bool appendError = false)
        {
            Error erro = null;

            if (this.WorkDate < Workspace.Instance.Config.MinDate || this.WorkDate > DateTime.Now)
            {
                erro = new Error { Description = string.Format("Data de emissão do documento {0} incorrecta.", this.DocumentNumber), Field = "WorkDate", TypeofError = this.GetType(), Value = this.WorkDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.WorkDate = this.Tooltip.WorkDate.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateSystemEntryDate(bool appendError = false)
        {
            Error erro = null;

            if (this.SystemEntryDate < Workspace.Instance.Config.MinDate || this.SystemEntryDate > DateTime.Now)
            {
                erro = new Error { Description = string.Format("Data da gravação do documento {0} incorrecta.", this.DocumentNumber), Field = "SystemEntryDate", TypeofError = this.GetType(), Value = this.SystemEntryDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.SystemEntryDate = this.Tooltip.SystemEntryDate.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }

        public Error[] ValidateDocumentStatus()
        {
            List<Error> listError = new List<Error>();

            if (this.DocumentStatus == null)
                listError.Add(new Error { Description = string.Format("Situação do documento {0} inexistente.", this.DocumentNumber), Field = "DocumentStatus", TypeofError = this.GetType(), UID = this.Pk });

            if (this.DocumentStatus != null)
            {
                if (this.DocumentStatus.WorkStatusDate < Workspace.Instance.Config.MinDate || this.DocumentStatus.WorkStatusDate > DateTime.Now)
                    listError.Add(new Error { Description = string.Format("Data e hora do estado atual do documento {0} incorrecta.", this.DocumentNumber), Field = "InvoiceStatusDate", TypeofError = this.GetType(), Value = this.DocumentStatus.WorkStatusDate.ToString(), UID = this.Pk });
                if (string.IsNullOrEmpty(this.DocumentStatus.Reason) == false && this.DocumentStatus.Reason.Length > 50)
                    listError.Add(new Error { Description = string.Format("Tamanho do motivo da alteração de estado {0} incorrecto.", this.DocumentNumber), Field = "Reason", TypeofError = this.GetType(), Value = this.DocumentStatus.Reason, UID = this.Pk });
                if (string.IsNullOrEmpty(this.DocumentStatus.SourceID) || this.DocumentStatus.SourceID.Length > 30)
                    listError.Add(new Error { Description = string.Format("Utilizador responsável pelo estado atual do documento {0} incorrecto.", this.DocumentNumber), Field = "SourceID", TypeofError = this.GetType(), Value = this.DocumentStatus.SourceID, UID = this.Pk });
            }

            return listError.ToArray();
        }
        public Error[] ValidateDocumentTotals()
        {
            List<Error> listError = new List<Error>();

            if (this.DocumentTotals == null)
                listError.Add(new Error { Description = string.Format("Totais do documento {0} inexistentes.", this.DocumentNumber), Field = "DocumentTotals", TypeofError = this.GetType(), UID = this.Pk });

            if (this.DocumentTotals != null)
            {
                if (this.DocumentTotals.Currency != null)
                {
                    if (this.DocumentTotals.Currency.CurrencyAmount < 0)
                        listError.Add(new Error { Description = string.Format("Valor total em moeda estrangeira do documento {0} incorrecto.", this.DocumentNumber), Field = "CurrencyAmount", TypeofError = this.GetType(), Value = this.DocumentTotals.Currency.CurrencyAmount.ToString(), UID = this.Pk });
                    if (string.IsNullOrEmpty(this.DocumentTotals.Currency.CurrencyCode) || this.DocumentTotals.Currency.CurrencyCode.Length > 3)
                        listError.Add(new Error { Description = string.Format("Tamanho do código de moeda do documento {0} incorrecto.", this.DocumentNumber), Field = "CurrencyCode", TypeofError = this.GetType(), Value = this.DocumentTotals.Currency.CurrencyCode, UID = this.Pk });
                    if (this.DocumentTotals.Currency.ExchangeRateSpecified && this.DocumentTotals.Currency.ExchangeRate < 0)
                        listError.Add(new Error { Description = string.Format("Taxa de câmbio do documento {0} incorrecta.", this.DocumentNumber), Field = "ExchangeRate", TypeofError = this.GetType(), Value = this.DocumentTotals.Currency.ExchangeRate.ToString(), UID = this.Pk });
                }

                if (this.DocumentTotals.GrossTotal < 0)
                    listError.Add(new Error { Description = string.Format("Total do documento {0} incorrecto.", this.DocumentNumber), Field = "GrossTotal", TypeofError = this.GetType(), Value = this.DocumentTotals.GrossTotal.ToString(), UID = this.Pk });
                if (this.DocumentTotals.NetTotal < 0)
                    listError.Add(new Error { Description = string.Format("Total do documento {0} sem impostos incorrecto.", this.DocumentNumber), Field = "NetTotal", TypeofError = this.GetType(), Value = this.DocumentTotals.NetTotal.ToString(), UID = this.Pk });
                if (this.DocumentTotals.TaxPayable < 0)
                    listError.Add(new Error { Description = string.Format("Valor do imposto a pagar do documento {0} incorrecto.", this.DocumentNumber), Field = "TaxPayable", TypeofError = this.GetType(), Value = this.DocumentTotals.TaxPayable.ToString(), UID = this.Pk });
            }

            return listError.ToArray();
        }
        #endregion
    }

    public partial class SourceDocumentsWorkingDocumentsWorkDocumentLine : BaseData, IDataErrorInfo
    {
        /// <summary>
        /// Link to the doc
        /// </summary>
        public string DocNo { get; set; }

        WorkingDocumentsLineToolTipService tooltip;
        public WorkingDocumentsLineToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new WorkingDocumentsLineToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get
            {
                StringBuilder error = new StringBuilder();

                // iterate over all of the properties
                // of this object - aggregating any validation errors
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this);
                foreach (PropertyDescriptor prop in props)
                {
                    String propertyError = this[prop.Name];
                    if (propertyError != string.Empty)
                        error.Append((error.Length != 0 ? ", " : "") + propertyError);
                }

                return error.Length == 0 ? null : error.ToString();
            }
        }

        [System.Runtime.CompilerServices.IndexerName("Items")]
        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "LineNumber")
                {
                    erro = ValidateLineNumber(appendError: true);
                }
                else if (columnName == "ProductCode")
                {
                    erro = ValidateProductCode(appendError: true);
                }
                else if (columnName == "Quantity")
                {
                    erro = ValidateQuantity(appendError: true);
                }
                else if (columnName == "UnitOfMeasure")
                {
                    erro = ValidateUnitOfMeasure(appendError: true);
                }
                else if (columnName == "UnitPrice")
                {
                    erro = ValidateUnitPrice(appendError: true);
                }
                else if (columnName == "TaxPointDate")
                {
                    erro = ValidateTaxPointDate(appendError: true);
                }
                return erro == null ? erro.Description : "";
            }
        }

        public Error ValidateLineNumber(bool appendError = false, string SupPk = "", string workingDocument = "")
        {
            Error erro = null;
            int num = -1;
            if (!string.IsNullOrEmpty(this.LineNumber))
                Int32.TryParse(this.LineNumber, out num);

            if (string.IsNullOrEmpty(this.LineNumber) || num == -1)
            {
                if (!string.IsNullOrEmpty(workingDocument))
                    workingDocument = string.Format(", documento {0}", workingDocument);

                erro = new Error { Description = string.Format("Número de linha incorrecto {0}.", workingDocument), Field = "LineNumber", TypeofError = this.GetType(), Value = this.LineNumber, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.LineNumber = this.Tooltip.LineNumber.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateProductCode(bool appendError = false, string SupPk = "", string workingDocument = "")
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductCode) || this.ProductCode.Length > 30)
            {
                if (!string.IsNullOrEmpty(workingDocument))
                    workingDocument = string.Format(" documento {0}", workingDocument);

                erro = new Error { Description = string.Format("Identificador do produto ou serviço incorrecto, {0} linha {1}.", workingDocument, this.LineNumber), Field = "ProductCode", TypeofError = this.GetType(), Value = this.ProductCode, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.ProductCode = this.Tooltip.ProductCode.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateProductDescription(bool appendError = false, string SupPk = "", string workingDocument = "")
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductDescription) || this.ProductDescription.Length > 200)
            {
                if (!string.IsNullOrEmpty(workingDocument))
                    workingDocument = string.Format(" documento {0}", workingDocument);

                erro = new Error { Description = string.Format("Descrição do produto ou serviço incorrecta, {0} linha {1}.", workingDocument, this.LineNumber), Field = "ProductDescription", TypeofError = this.GetType(), Value = this.ProductDescription, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.ProductDescription = this.Tooltip.ProductDescription.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateQuantity(bool appendError = false, string SupPk = "", string workingDocument = "")
        {
            Error erro = null;
            if (this.Quantity <= 0)
            {
                if (!string.IsNullOrEmpty(workingDocument))
                    workingDocument = string.Format(" documento {0}", workingDocument);

                erro = new Error { Description = string.Format("Quantidade incorrecta, {0} linha {1}.", workingDocument, this.LineNumber), Field = "Quantity", TypeofError = this.GetType(), Value = this.Quantity.ToString(), UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.Quantity = this.Tooltip.Quantity.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateUnitOfMeasure(bool appendError = false, string SupPk = "", string workingDocument = "")
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.UnitOfMeasure) || this.UnitOfMeasure.Length > 20)
            {
                if (!string.IsNullOrEmpty(workingDocument))
                    workingDocument = string.Format(" documento {0}", workingDocument);

                erro = new Error { Description = string.Format("Unidade de medida incorrecta, {0} linha {1}.", workingDocument, this.LineNumber), Field = "UnitOfMeasure", TypeofError = this.GetType(), Value = this.UnitOfMeasure, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.UnitOfMeasure = this.Tooltip.UnitOfMeasure.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateUnitPrice(bool appendError = false, string SupPk = "", string workingDocument = "")
        {
            Error erro = null;
            if (this.UnitPrice == 0)
            {
                if (!string.IsNullOrEmpty(workingDocument))
                    workingDocument = string.Format(" documento {0}", workingDocument);

                erro = new Error { Description = string.Format("Preço unitário incorrecto, {0} linha {1}.", workingDocument, this.LineNumber), Field = "UnitPrice", TypeofError = this.GetType(), Value = this.UnitPrice.ToString(), UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.UnitPrice = this.Tooltip.UnitPrice.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateTaxPointDate(bool appendError = false, string SupPk = "", string workingDocument = "")
        {
            Error erro = null;
            if (this.TaxPointDate < Workspace.Instance.Config.MinDate || this.TaxPointDate > DateTime.Now)
            {
                if (!string.IsNullOrEmpty(workingDocument))
                    workingDocument = string.Format(" documento {0}", workingDocument);

                erro = new Error { Description = string.Format("Data de envio da mercadoria ou prestação do serviço incorrecta, {0} linha {1}.", workingDocument, this.LineNumber), Field = "TaxPointDate", TypeofError = this.GetType(), Value = this.TaxPointDate.ToString(), UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.TaxPointDate = this.Tooltip.TaxPointDate.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }

        public Error[] ValidateOrderReferences(string SupPk = "", string workingDocument = "")
        {
            List<Error> listError = new List<Error>();

            if (this.OrderReferences != null && this.OrderReferences.Length > 0)
            {
                foreach (var referencia in this.OrderReferences)
                {
                    if (string.IsNullOrEmpty(referencia.OriginatingON) == false && referencia.OriginatingON.Length > 60)
                        listError.Add(new Error { Description = string.Format("Tamanho do número do documento de origem na linha {0} do documento {1} incorrecto.", this.LineNumber, workingDocument), Field = "OriginatingON", TypeofError = this.GetType(), Value = referencia.OriginatingON, UID = this.Pk, SupUID = SupPk });
                    if (referencia.OrderDateSpecified && (referencia.OrderDate < Workspace.Instance.Config.MinDate || referencia.OrderDate > DateTime.Now))
                        listError.Add(new Error { Description = string.Format("Data do documento de origem na linha {0} do documento {1} incorrecto.", this.LineNumber, workingDocument), Field = "OrderDate", TypeofError = this.GetType(), Value = referencia.OrderDate.ToString(), UID = this.Pk, SupUID = SupPk });
                }
            }

            return listError.ToArray();
        }
        public Error[] ValidateTax(string SupPk = "", string workingDocument = "")
        {
            List<Error> listError = new List<Error>();

            if (this.Tax == null)
                listError.Add(new Error { Description = string.Format("Taxa de imposto na linha {0} do documento {1} inexistente.", this.LineNumber, workingDocument), Field = "Tax", TypeofError = this.GetType(), UID = this.Pk, SupUID = SupPk });

            if (this.Tax != null)
            {
                if (this.Tax.ItemElementName == ItemChoiceType1.TaxAmount && this.Tax.Item < 0)
                    listError.Add(new Error { Description = string.Format("Montante do imposto na linha {0} do documento {1} incorrecto.", this.LineNumber, workingDocument), Field = "TaxAmount", TypeofError = this.GetType(), Value = this.Tax.Item.ToString(), UID = this.Pk, SupUID = SupPk });
                if (this.Tax.ItemElementName == ItemChoiceType1.TaxPercentage && (this.Tax.Item < 0 || this.Tax.Item > 100))
                    listError.Add(new Error { Description = string.Format("Percentagem da taxa do imposto na linha {0} do documento {1} incorrecto.", this.LineNumber, workingDocument), Field = "TaxPercentage", TypeofError = this.GetType(), Value = this.Tax.Item.ToString(), UID = this.Pk, SupUID = SupPk });
                if (string.IsNullOrEmpty(this.Tax.TaxCode) || this.Tax.TaxCode.Length > 10)
                    listError.Add(new Error { Description = string.Format("Código da taxa na linha {0} do documento {1} incorrecto.", this.LineNumber, workingDocument), Field = "TaxCode", TypeofError = this.GetType(), Value = this.Tax.TaxCode, UID = this.Pk, SupUID = SupPk });
                if (string.IsNullOrEmpty(this.Tax.TaxCountryRegion) || this.Tax.TaxCountryRegion.Length > 5)
                    listError.Add(new Error { Description = string.Format("País ou região do imposto na linha {0} do documento {1} incorrecto.", this.LineNumber, workingDocument), Field = "TaxCountryRegion", TypeofError = this.GetType(), Value = this.Tax.TaxCountryRegion, UID = this.Pk, SupUID = SupPk });
            }

            return listError.ToArray();
        }
    }

    public partial class SourceDocumentsSalesInvoicesInvoice : BaseData, IDataErrorInfo
    {
        public string HashTest { get; set; }

        SourceDocumentsToolTipService tooltip;
        public SourceDocumentsToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new SourceDocumentsToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get
            {
                StringBuilder error = new StringBuilder();

                // iterate over all of the properties
                // of this object - aggregating any validation errors
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this);
                foreach (PropertyDescriptor prop in props)
                {
                    String propertyError = this[prop.Name];
                    if (propertyError != string.Empty)
                        error.Append((error.Length != 0 ? ", " : "") + propertyError);
                }

                return error.Length == 0 ? null : error.ToString();
            }
        }

        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "InvoiceNo")
                {
                    erro = ValidateInvoiceNo(appendError: true);
                }
                else if (columnName == "Hash")
                {
                    erro = ValidateHash(appendError: true);
                }
                else if (columnName == "HashControl")
                {
                    erro = ValidateHashControl(appendError: true);
                }
                else if (columnName == "Period")
                {
                    erro = ValidatePeriod(appendError: true);
                }
                else if (columnName == "InvoiceDate")
                {
                    erro = ValidateInvoiceDate(appendError: true);
                }
                else if (columnName == "SystemEntryDate")
                {
                    erro = ValidateSystemEntryDate(appendError: true);
                }
                else if (columnName == "TransactionID")
                {
                    erro = ValidateTransactionID(appendError: true);
                }
                else if (columnName == "CustomerID")
                {
                    erro = ValidateCustomerID(appendError: true);
                }
                else if (columnName == "SourceID")
                {
                    erro = ValidateSourceID(appendError: true);
                }
                else if (columnName == "MovementEndTime")
                {
                    erro = ValidateMovementEndTime(appendError: true);
                }
                else if (columnName == "MovementStartTime")
                {
                    erro = ValidateMovementStartTime(appendError: true);
                }

                return erro == null ? erro.Description : null;
            }
        }

        #region Validation
        public Error ValidateInvoiceNo(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.InvoiceNo) || this.InvoiceNo.Length > 60)
            {
                erro = new Error { Description = "Identificação única com tamanho incorrecto.", Field = "InvoiceNo", TypeofError = this.GetType(), Value = this.InvoiceNo, UID = this.Pk };
                if (appendError)
                    this.Tooltip.InvoiceNo = this.Tooltip.InvoiceNo.FormatTooltipWithError(erro.Description);
            }
            else if (!Regex.IsMatch(this.InvoiceNo, "([a-zA-Z0-9./_-])+ ([a-zA-Z0-9]*/[0-9]+)"))
            {
                erro = new Error { Description = "Identificação única com caracteres não permitidos.", Field = "InvoiceNo", TypeofError = this.GetType(), Value = this.InvoiceNo, UID = this.Pk };
                if (appendError)
                    this.Tooltip.InvoiceNo = this.Tooltip.InvoiceNo.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateHash(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.Hash) || this.Hash.Length != 172)
            {
                erro = new Error { Description = string.Format("Assinatura do documento {0} de tamanho incorrecto.", this.InvoiceNo), Field = "Hash", TypeofError = this.GetType(), Value = this.Hash, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Hash = this.Tooltip.Hash.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateHashControl(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.HashControl) || this.HashControl.Length > 40)
            {
                erro = new Error { Description = string.Format("Versão da chave privada utilizada na assinatura do documento {0} incorrecta.", this.InvoiceNo), Field = "HashControl", TypeofError = this.GetType(), Value = this.HashControl, UID = this.Pk };
                if (appendError)
                    this.Tooltip.HashControl = this.Tooltip.HashControl.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidatePeriod(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.Period) == false)
            {
                int periodo = -1;
                Int32.TryParse(this.Period, out periodo);

                if (periodo < 1 || periodo > 12)
                {
                    erro = new Error { Description = string.Format("Mês do período de tributação do documento {0} incorrecto.", this.InvoiceNo), Field = "Period", TypeofError = this.GetType(), Value = this.Period, UID = this.Pk };
                    if (appendError)
                        this.Tooltip.Period = this.Tooltip.Period.FormatTooltipWithError(erro.Description);
                }
            }

            return erro;
        }
        public Error ValidateInvoiceDate(bool appendError = false)
        {
            Error erro = null;

            if (this.InvoiceDate < Workspace.Instance.Config.MinDate || this.InvoiceDate > DateTime.Now)
            {
                erro = new Error { Description = string.Format("Data de emissão do documento {0} incorrecta.", this.InvoiceNo), Field = "InvoiceDate", TypeofError = this.GetType(), Value = this.InvoiceDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.InvoiceDate = this.Tooltip.InvoiceDate.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateSystemEntryDate(bool appendError = false)
        {
            Error erro = null;

            if (this.SystemEntryDate < Workspace.Instance.Config.MinDate || this.SystemEntryDate > DateTime.Now)
            {
                erro = new Error { Description = string.Format("Data da gravação do documento {0} incorrecta.", this.InvoiceNo), Field = "SystemEntryDate", TypeofError = this.GetType(), Value = this.SystemEntryDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.SystemEntryDate = this.Tooltip.SystemEntryDate.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateTransactionID(bool appendError = false)
        {
            Error erro = null;

            if (!string.IsNullOrEmpty(this.TransactionID) && this.TransactionID.Length > 70)
            {
                erro = new Error { Description = string.Format("Identificador da transacção do documento {0} incorrecto.", this.InvoiceNo), Field = "TransactionID", TypeofError = this.GetType(), Value = this.TransactionID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.TransactionID = this.Tooltip.TransactionID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateCustomerID(bool appendError = false)
        {
            Error erro = null;

            if (string.IsNullOrEmpty(this.CustomerID) || this.CustomerID.Length > 30)
            {
                erro = new Error { Description = string.Format("Chave única da tabela de clientes no documento {0} incorrecta.", this.InvoiceNo), Field = "CustomerID", TypeofError = this.GetType(), Value = this.CustomerID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.CustomerID = this.Tooltip.CustomerID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateSourceID(bool appendError = false)
        {
            Error erro = null;

            if (SAFT.SaftAnalyser.Instance.FileVersion != SaftFileVersion.V10101)
            {
                if (string.IsNullOrEmpty(this.SourceID) || this.SourceID.Length > 30)
                {
                    erro = new Error { Description = string.Format("Utilizador que gerou o documento {0} incorrecto.", this.InvoiceNo), Field = "CustomerID", TypeofError = this.GetType(), Value = this.CustomerID, UID = this.Pk };
                    if (appendError)
                        this.Tooltip.GeneratedDocumentUserSourceID = this.Tooltip.GeneratedDocumentUserSourceID.FormatTooltipWithError(erro.Description);
                }
            }

            return erro;
        }
        public Error ValidateMovementEndTime(bool appendError = false)
        {
            Error erro = null;

            if (this.MovementEndTimeSpecified && (this.MovementEndTime < Workspace.Instance.Config.MinDate || this.MovementEndTime > DateTime.Now))
            {
                erro = new Error { Description = string.Format("Data e hora de fim de transporte do documento {0} incorrecta.", this.InvoiceNo), Field = "MovementEndTime", TypeofError = this.GetType(), Value = this.MovementEndTime.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.MovementEndTime = this.Tooltip.MovementEndTime.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateMovementStartTime(bool appendError = false)
        {
            Error erro = null;

            if (this.MovementStartTimeSpecified && (this.MovementStartTime < Workspace.Instance.Config.MinDate || this.MovementStartTime > DateTime.Now))
            {
                erro = new Error { Description = string.Format("Data e hora de início de transporte do documento {0} incorrecta.", this.InvoiceNo), Field = "MovementStartTime", TypeofError = this.GetType(), Value = this.MovementStartTime.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.MovementStartTime = this.Tooltip.MovementStartTime.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }

        public Error[] ValidateDocumentStatus()
        {
            List<Error> listError = new List<Error>();

            if (this.DocumentStatus == null)
                listError.Add(new Error { Description = string.Format("Situação do documento {0} inexistente.", this.InvoiceNo), Field = "DocumentStatus", TypeofError = this.GetType(), UID = this.Pk });

            if (this.DocumentStatus != null && SAFT.SaftAnalyser.Instance.FileVersion != SaftFileVersion.V10101)
            {
                if (this.DocumentStatus.InvoiceStatusDate < Workspace.Instance.Config.MinDate || this.DocumentStatus.InvoiceStatusDate > DateTime.Now)
                    listError.Add(new Error { Description = string.Format("Data e hora do estado atual do documento {0} incorrecta.", this.InvoiceNo), Field = "InvoiceStatusDate", TypeofError = this.GetType(), Value = this.DocumentStatus.InvoiceStatusDate.ToString(), UID = this.Pk });
                if (string.IsNullOrEmpty(this.DocumentStatus.Reason) == false && this.DocumentStatus.Reason.Length > 50)
                    listError.Add(new Error { Description = string.Format("Tamanho do motivo da alteração de estado {0} incorrecto.", this.InvoiceNo), Field = "Reason", TypeofError = this.GetType(), Value = this.DocumentStatus.Reason, UID = this.Pk });
                if (string.IsNullOrEmpty(this.DocumentStatus.SourceID) || this.DocumentStatus.SourceID.Length > 30)
                    listError.Add(new Error { Description = string.Format("Utilizador responsável pelo estado atual do documento {0} incorrecto.", this.InvoiceNo), Field = "SourceID", TypeofError = this.GetType(), Value = this.DocumentStatus.SourceID, UID = this.Pk });
            }

            return listError.ToArray();
        }
        public Error[] ValidateSpecialRegimes()
        {
            List<Error> listError = new List<Error>();

            if (this.SpecialRegimes != null)
            {
                int auto = -1;
                Int32.TryParse(this.SpecialRegimes.SelfBillingIndicator, out auto);
                if (string.IsNullOrEmpty(this.SpecialRegimes.SelfBillingIndicator) || (auto != 0 && auto != 1))
                    listError.Add(new Error { Description = string.Format("Indicador de autofaturação do documento {0} incorrecto.", this.InvoiceNo), Field = "SelfBillingIndicator", TypeofError = this.GetType(), Value = this.SpecialRegimes.SelfBillingIndicator, UID = this.Pk });

                if (SAFT.SaftAnalyser.Instance.FileVersion == SaftFileVersion.V10301)
                {
                    if (string.IsNullOrEmpty(this.SpecialRegimes.CashVATSchemeIndicator) || (this.SpecialRegimes.CashVATSchemeIndicator != "0" && this.SpecialRegimes.CashVATSchemeIndicator != "1"))
                        listError.Add(new Error { Description = string.Format("Indicador da existência de adesão ao regime de IVA de Caixa do documento {0} incorrecto.", this.InvoiceNo), Field = "CashVATSchemeIndicator", TypeofError = this.GetType(), Value = this.SpecialRegimes.CashVATSchemeIndicator, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.SpecialRegimes.ThirdPartiesBillingIndicator) || (this.SpecialRegimes.ThirdPartiesBillingIndicator != "0" && this.SpecialRegimes.CashVATSchemeIndicator != "1"))
                        listError.Add(new Error { Description = string.Format("Indicador da existência de adesão ao regime de IVA de Caixa do documento {0} incorrecto.", this.InvoiceNo), Field = "ThirdPartiesBillingIndicator", TypeofError = this.GetType(), Value = this.SpecialRegimes.ThirdPartiesBillingIndicator, UID = this.Pk });
                }
            }

            return listError.ToArray();
        }
        public Error[] ValidateShipTo()
        {
            List<Error> listError = new List<Error>();

            if (this.ShipTo != null)
            {
                if (this.ShipTo.Address != null)
                {
                    if (string.IsNullOrEmpty(this.ShipTo.Address.AddressDetail) || this.ShipTo.Address.AddressDetail.Length > 100)
                        listError.Add(new Error { Description = string.Format("Tamanho da morada detalhada do documento {0} do local de descarga incorrecto.", this.InvoiceNo), Field = "AddressDetail", TypeofError = this.GetType(), Value = this.ShipTo.Address.AddressDetail, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.BuildingNumber) == false && this.ShipTo.Address.BuildingNumber.Length > 10)
                        listError.Add(new Error { Description = string.Format("Tamanho do número de polícia do documento {0} do local de descarga incorrecto.", this.InvoiceNo), Field = "BuildingNumber", TypeofError = this.GetType(), Value = this.ShipTo.Address.BuildingNumber, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.City) || this.ShipTo.Address.City.Length > 50)
                        listError.Add(new Error { Description = string.Format("Tamanho da localidade do documento {0} do local de descarga incorrecto.", this.InvoiceNo), Field = "City", TypeofError = this.GetType(), Value = this.ShipTo.Address.City, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.Country) || this.ShipTo.Address.Country.Length != 2)
                        listError.Add(new Error { Description = string.Format("Tamanho do País do documento {0} do local de descarga incorrecto.", this.InvoiceNo), Field = "Country", TypeofError = this.GetType(), Value = this.ShipTo.Address.Country, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.PostalCode) || this.ShipTo.Address.PostalCode.Length > 20)
                        listError.Add(new Error { Description = string.Format("Tamanho do código postal do documento {0} do local de descarga incorrecto.", this.InvoiceNo), Field = "PostalCode", TypeofError = this.GetType(), Value = this.ShipTo.Address.PostalCode, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.Region) == false && this.ShipTo.Address.Region.Length > 50)
                        listError.Add(new Error { Description = string.Format("Tamanho do distrito do documento {0} do local de descarga incorrecto.", this.InvoiceNo), Field = "Region", TypeofError = this.GetType(), Value = this.ShipTo.Address.Region, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipTo.Address.StreetName) == false && this.ShipTo.Address.StreetName.Length > 90)
                        listError.Add(new Error { Description = string.Format("Tamanho do nome da rua do documento {0} do local de descarga incorrecto.", this.InvoiceNo), Field = "StreetName", TypeofError = this.GetType(), Value = this.ShipTo.Address.StreetName, UID = this.Pk });
                }
                if (this.ShipTo.DeliveryDate < Workspace.Instance.Config.MinDate || this.ShipTo.DeliveryDate > DateTime.Now)
                    listError.Add(new Error { Description = string.Format("Data da entrega do documento {0} incorrecto.", this.InvoiceNo), Field = "DeliveryDate", TypeofError = this.GetType(), Value = this.ShipTo.DeliveryDate.ToString(), UID = this.Pk });
            }

            return listError.ToArray();
        }
        public Error[] ValidateShipFrom()
        {
            List<Error> listError = new List<Error>();

            if (this.ShipFrom != null)
            {
                if (this.ShipFrom.Address != null)
                {
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.AddressDetail) || this.ShipFrom.Address.AddressDetail.Length > 100)
                        listError.Add(new Error { Description = string.Format("Tamanho da morada detalhada do documento {0} do local de carga incorrecto.", this.InvoiceNo), Field = "AddressDetail", TypeofError = this.GetType(), Value = this.ShipFrom.Address.AddressDetail, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.BuildingNumber) == false && this.ShipFrom.Address.BuildingNumber.Length > 10)
                        listError.Add(new Error { Description = string.Format("Tamanho do número de polícia do documento {0} do local de carga incorrecto.", this.InvoiceNo), Field = "BuildingNumber", TypeofError = this.GetType(), Value = this.ShipFrom.Address.BuildingNumber, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.City) || this.ShipFrom.Address.City.Length > 50)
                        listError.Add(new Error { Description = string.Format("Tamanho da localidade do documento {0} do local de carga incorrecto.", this.InvoiceNo), Field = "City", TypeofError = this.GetType(), Value = this.ShipFrom.Address.City, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.Country) || this.ShipFrom.Address.Country.Length != 2)
                        listError.Add(new Error { Description = string.Format("Tamanho do País do documento {0} do local de carga incorrecto.", this.InvoiceNo), Field = "Country", TypeofError = this.GetType(), Value = this.ShipFrom.Address.Country, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.PostalCode) || this.ShipFrom.Address.PostalCode.Length > 20)
                        listError.Add(new Error { Description = string.Format("Tamanho do código postal do documento {0} do local de carga incorrecto.", this.InvoiceNo), Field = "PostalCode", TypeofError = this.GetType(), Value = this.ShipFrom.Address.PostalCode, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.Region) == false && this.ShipFrom.Address.Region.Length > 50)
                        listError.Add(new Error { Description = string.Format("Tamanho do distrito do documento {0} do local de carga incorrecto.", this.InvoiceNo), Field = "Region", TypeofError = this.GetType(), Value = this.ShipFrom.Address.Region, UID = this.Pk });
                    if (string.IsNullOrEmpty(this.ShipFrom.Address.StreetName) == false && this.ShipFrom.Address.StreetName.Length > 90)
                        listError.Add(new Error { Description = string.Format("Tamanho do nome da rua do documento {0} do local de carga incorrecto.", this.InvoiceNo), Field = "StreetName", TypeofError = this.GetType(), Value = this.ShipFrom.Address.StreetName, UID = this.Pk });
                }
                if (this.ShipFrom.DeliveryDate < Workspace.Instance.Config.MinDate || this.ShipFrom.DeliveryDate > DateTime.Now)
                    listError.Add(new Error { Description = string.Format("Data da receção do documento {0} incorrecto.", this.InvoiceNo), Field = "DeliveryDate", TypeofError = this.GetType(), Value = this.ShipFrom.DeliveryDate.ToString(), UID = this.Pk });
            }

            return listError.ToArray();
        }
        public Error[] ValidateDocumentTotals()
        {
            List<Error> listError = new List<Error>();

            if (this.DocumentTotals == null)
                listError.Add(new Error { Description = string.Format("Totais do documento {0} inexistentes.", this.InvoiceNo), Field = "DocumentTotals", TypeofError = this.GetType(), UID = this.Pk });

            if (this.DocumentTotals != null)
            {
                if (this.DocumentTotals.Currency != null)
                {
                    if (this.DocumentTotals.Currency.CurrencyAmount < 0)
                        listError.Add(new Error { Description = string.Format("Valor total em moeda estrangeira do documento {0} incorrecto.", this.InvoiceNo), Field = "CurrencyAmount", TypeofError = this.GetType(), Value = this.DocumentTotals.Currency.CurrencyAmount.ToString(), UID = this.Pk });
                    if (string.IsNullOrEmpty(this.DocumentTotals.Currency.CurrencyCode) || this.DocumentTotals.Currency.CurrencyCode.Length > 3)
                        listError.Add(new Error { Description = string.Format("Tamanho do código de moeda do documento {0} incorrecto.", this.InvoiceNo), Field = "CurrencyCode", TypeofError = this.GetType(), Value = this.DocumentTotals.Currency.CurrencyCode, UID = this.Pk });
                    if (this.DocumentTotals.Currency.ExchangeRateSpecified && this.DocumentTotals.Currency.ExchangeRate < 0)
                        listError.Add(new Error { Description = string.Format("Taxa de câmbio do documento {0} incorrecta.", this.InvoiceNo), Field = "ExchangeRate", TypeofError = this.GetType(), Value = this.DocumentTotals.Currency.ExchangeRate.ToString(), UID = this.Pk });
                }

                if (this.DocumentTotals.Settlement != null && this.DocumentTotals.Settlement.Length > 0)
                {
                    foreach (var acordo in this.DocumentTotals.Settlement)
                    {
                        if (string.IsNullOrEmpty(acordo.PaymentTerms) == false && acordo.PaymentTerms.Length > 100)
                            listError.Add(new Error { Description = string.Format("Tamanho do acordo de pagamento do documento {0} incorrecto.", this.InvoiceNo), Field = "PaymentTerms", TypeofError = this.GetType(), Value = acordo.PaymentTerms, UID = this.Pk });
                        if (acordo.SettlementAmountSpecified && acordo.SettlementAmount < 0)
                            listError.Add(new Error { Description = string.Format("Acordos de descontos futuros do documento {0} incorrecto.", this.InvoiceNo), Field = "SettlementAmount", TypeofError = this.GetType(), Value = acordo.SettlementAmount.ToString(), UID = this.Pk });
                        if (acordo.SettlementDateSpecified && acordo.SettlementDate < Workspace.Instance.Config.MinDate)
                            listError.Add(new Error { Description = string.Format("Data acordada para o desconto do documento {0} incorrecto.", this.InvoiceNo), Field = "SettlementDate", TypeofError = this.GetType(), Value = acordo.SettlementDate.ToString(), UID = this.Pk });
                        if (string.IsNullOrEmpty(acordo.SettlementDiscount) == false && acordo.SettlementDiscount.Length > 30)
                            listError.Add(new Error { Description = string.Format("Montante do desconto do documento {0} incorrecto.", this.InvoiceNo), Field = "SettlementAmount", TypeofError = this.GetType(), Value = acordo.SettlementAmount.ToString(), UID = this.Pk });
                    }
                }

                if (this.DocumentTotals.GrossTotal < 0)
                    listError.Add(new Error { Description = string.Format("Total do documento {0} incorrecto.", this.InvoiceNo), Field = "GrossTotal", TypeofError = this.GetType(), Value = this.DocumentTotals.GrossTotal.ToString(), UID = this.Pk });
                if (this.DocumentTotals.NetTotal < 0)
                    listError.Add(new Error { Description = string.Format("Total do documento {0} sem impostos incorrecto.", this.InvoiceNo), Field = "NetTotal", TypeofError = this.GetType(), Value = this.DocumentTotals.NetTotal.ToString(), UID = this.Pk });
                if (this.DocumentTotals.TaxPayable < 0)
                    listError.Add(new Error { Description = string.Format("Valor do imposto a pagar do documento {0} incorrecto.", this.InvoiceNo), Field = "TaxPayable", TypeofError = this.GetType(), Value = this.DocumentTotals.TaxPayable.ToString(), UID = this.Pk });
            }

            return listError.ToArray();
        }
        #endregion
    }

    public partial class SourceDocumentsSalesInvoicesInvoiceLine : BaseData, IDataErrorInfo
    {
        /// <summary>
        /// Link to the invoice
        /// </summary>
        public string InvoiceNo { get; set; }

        SourceDocumentsSalesInvoicesInvoiceLineToolTipService tooltip;
        public SourceDocumentsSalesInvoicesInvoiceLineToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new SourceDocumentsSalesInvoicesInvoiceLineToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        [System.Runtime.CompilerServices.IndexerName("Items")]
        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "LineNumber")
                {
                    erro = ValidateLineNumber(appendError: true);
                }
                else if (columnName == "ProductCode")
                {
                    erro = ValidateProductCode(appendError: true);
                }
                else if (columnName == "ProductDescription")
                {
                    erro = ValidateProductDescription(appendError: true);
                }
                else if (columnName == "Quantity")
                {
                    erro = ValidateQuantity(appendError: true);
                }
                else if (columnName == "UnitOfMeasure")
                {
                    erro = ValidateUnitOfMeasure(appendError: true);
                }
                else if (columnName == "UnitPrice")
                {
                    erro = ValidateUnitPrice(appendError: true);
                }
                else if (columnName == "TaxPointDate")
                {
                    erro = ValidateTaxPointDate(appendError: true);
                }

                return erro == null ? erro.Description : null;
            }
        }

        #region
        public Error ValidateLineNumber(bool appendError = false, string SupPk = "", string invoiceNo = "")
        {
            Error erro = null;
            int num = -1;
            if (!string.IsNullOrEmpty(this.LineNumber))
                Int32.TryParse(this.LineNumber, out num);

            if (string.IsNullOrEmpty(this.LineNumber) || num == -1)
            {
                if (!string.IsNullOrEmpty(invoiceNo))
                    invoiceNo = string.Format(", documento {0}", invoiceNo);

                erro = new Error { Description = string.Format("Número de linha incorrecto {0}.", invoiceNo), Field = "LineNumber", TypeofError = this.GetType(), Value = this.LineNumber, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.LineNumber = this.Tooltip.LineNumber.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateProductCode(bool appendError = false, string SupPk = "", string invoiceNo = "")
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductCode) || this.ProductCode.Length > 30)
            {
                if (!string.IsNullOrEmpty(invoiceNo))
                    invoiceNo = string.Format(" documento {0}", invoiceNo);

                erro = new Error { Description = string.Format("Identificador do produto ou serviço incorrecto, {0} linha {1}.", invoiceNo, this.LineNumber), Field = "ProductCode", TypeofError = this.GetType(), Value = this.ProductCode, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.ProductCode = this.Tooltip.ProductCode.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateProductDescription(bool appendError = false, string SupPk = "", string invoiceNo = "")
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductDescription) || this.ProductDescription.Length > 200)
            {
                if (!string.IsNullOrEmpty(invoiceNo))
                    invoiceNo = string.Format(" documento {0}", invoiceNo);

                erro = new Error { Description = string.Format("Descrição do produto ou serviço incorrecta, {0} linha {1}.", invoiceNo, this.LineNumber), Field = "ProductDescription", TypeofError = this.GetType(), Value = this.ProductDescription, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.ProductDescription = this.Tooltip.ProductDescription.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateQuantity(bool appendError = false, string SupPk = "", string invoiceNo = "")
        {
            Error erro = null;
            if (this.Quantity <= 0)
            {
                if (!string.IsNullOrEmpty(invoiceNo))
                    invoiceNo = string.Format(" documento {0}", invoiceNo);

                erro = new Error { Description = string.Format("Quantidade incorrecta, {0} linha {1}.", invoiceNo, this.LineNumber), Field = "Quantity", TypeofError = this.GetType(), Value = this.Quantity.ToString(), UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.Quantity = this.Tooltip.Quantity.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateUnitOfMeasure(bool appendError = false, string SupPk = "", string invoiceNo = "")
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.UnitOfMeasure) || this.UnitOfMeasure.Length > 20)
            {
                if (!string.IsNullOrEmpty(invoiceNo))
                    invoiceNo = string.Format(" documento {0}", invoiceNo);

                erro = new Error { Description = string.Format("Unidade de medida incorrecta, {0} linha {1}.", invoiceNo, this.LineNumber), Field = "UnitOfMeasure", TypeofError = this.GetType(), Value = this.UnitOfMeasure, UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.UnitOfMeasure = this.Tooltip.UnitOfMeasure.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateUnitPrice(bool appendError = false, string SupPk = "", string invoiceNo = "")
        {
            Error erro = null;
            if (this.UnitPrice == 0)
            {
                if (!string.IsNullOrEmpty(invoiceNo))
                    invoiceNo = string.Format(" documento {0}", invoiceNo);

                erro = new Error { Description = string.Format("Preço unitário incorrecto, {0} linha {1}.", invoiceNo, this.LineNumber), Field = "UnitPrice", TypeofError = this.GetType(), Value = this.UnitPrice.ToString(), UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.UnitPrice = this.Tooltip.UnitPrice.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateTaxPointDate(bool appendError = false, string SupPk = "", string invoiceNo = "")
        {
            Error erro = null;
            if (this.TaxPointDate < Workspace.Instance.Config.MinDate || this.TaxPointDate > DateTime.Now)
            {
                if (!string.IsNullOrEmpty(invoiceNo))
                    invoiceNo = string.Format(" documento {0}", invoiceNo);

                erro = new Error { Description = string.Format("Data de envio da mercadoria ou prestação do serviço incorrecta, {0} linha {1}.", invoiceNo, this.LineNumber), Field = "TaxPointDate", TypeofError = this.GetType(), Value = this.TaxPointDate.ToString(), UID = this.Pk, SupUID = SupPk };
                if (appendError)
                    this.Tooltip.TaxPointDate = this.Tooltip.TaxPointDate.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }

        public Error[] ValidateOrderReferences(string SupPk = "", string invoiceNo = "")
        {
            List<Error> listError = new List<Error>();

            if (this.OrderReferences != null && this.OrderReferences.Length > 0)
            {
                foreach (var referencia in this.OrderReferences)
                {
                    if (string.IsNullOrEmpty(referencia.OriginatingON) == false && referencia.OriginatingON.Length > 60)
                        listError.Add(new Error { Description = string.Format("Tamanho do número do documento de origem na linha {0} do documento {1} incorrecto.", this.LineNumber, invoiceNo), Field = "OriginatingON", TypeofError = this.GetType(), Value = referencia.OriginatingON, UID = this.Pk, SupUID = SupPk });
                    if (referencia.OrderDateSpecified && (referencia.OrderDate < Workspace.Instance.Config.MinDate || referencia.OrderDate > DateTime.Now))
                        listError.Add(new Error { Description = string.Format("Data do documento de origem na linha {0} do documento {1} incorrecto.", this.LineNumber, invoiceNo), Field = "OrderDate", TypeofError = this.GetType(), Value = referencia.OrderDate.ToString(), UID = this.Pk, SupUID = SupPk });
                }
            }

            return listError.ToArray();
        }
        public Error[] ValidateReferences(string SupPk = "", string invoiceNo = "")
        {
            List<Error> listError = new List<Error>();

            if (this.References != null && this.References.Length > 0)
            {
                foreach (var referencia in this.References)
                {
                    if (string.IsNullOrEmpty(referencia.Reason) == false && referencia.Reason.Length > 50)
                        listError.Add(new Error { Description = string.Format("Tamanho do motivo da emissão na linha {0} do documento {1} incorrecto.", this.LineNumber, invoiceNo), Field = "Reason", TypeofError = this.GetType(), Value = referencia.Reason, UID = this.Pk, SupUID = SupPk });
                    if (string.IsNullOrEmpty(referencia.Reference) == false && referencia.Reference.Length > 60)
                        listError.Add(new Error { Description = string.Format("Tamanho da referência à fatura ou fatura simplificada na linha {0} do documento {1} incorrecto.", this.LineNumber, invoiceNo), Field = "Reference", TypeofError = this.GetType(), Value = referencia.Reference, UID = this.Pk, SupUID = SupPk });
                }
            }

            return listError.ToArray();
        }
        public Error[] ValidateTax(string SupPk = "", string invoiceNo = "")
        {
            List<Error> listError = new List<Error>();

            if (this.Tax == null)
                listError.Add(new Error { Description = string.Format("Taxa de imposto na linha {0} do documento {1} inexistente.", this.LineNumber, invoiceNo), Field = "Tax", TypeofError = this.GetType(), UID = this.Pk, SupUID = SupPk });

            if (this.Tax != null)
            {
                if (this.Tax.ItemElementName == ItemChoiceType1.TaxAmount && this.Tax.Item < 0)
                    listError.Add(new Error { Description = string.Format("Montante do imposto na linha {0} do documento {1} incorrecto.", this.LineNumber, invoiceNo), Field = "TaxAmount", TypeofError = this.GetType(), Value = this.Tax.Item.ToString(), UID = this.Pk, SupUID = SupPk });
                if (this.Tax.ItemElementName == ItemChoiceType1.TaxPercentage && (this.Tax.Item < 0 || this.Tax.Item > 100))
                    listError.Add(new Error { Description = string.Format("Percentagem da taxa do imposto na linha {0} do documento {1} incorrecto.", this.LineNumber, invoiceNo), Field = "TaxPercentage", TypeofError = this.GetType(), Value = this.Tax.Item.ToString(), UID = this.Pk, SupUID = SupPk });
                if (string.IsNullOrEmpty(this.Tax.TaxCode) || this.Tax.TaxCode.Length > 10)
                    listError.Add(new Error { Description = string.Format("Código da taxa na linha {0} do documento {1} incorrecto.", this.LineNumber, invoiceNo), Field = "TaxCode", TypeofError = this.GetType(), Value = this.Tax.TaxCode, UID = this.Pk, SupUID = SupPk });
                if (string.IsNullOrEmpty(this.Tax.TaxCountryRegion) || this.Tax.TaxCountryRegion.Length > 5)
                    listError.Add(new Error { Description = string.Format("País ou região do imposto na linha {0} do documento {1} incorrecto.", this.LineNumber, invoiceNo), Field = "TaxCountryRegion", TypeofError = this.GetType(), Value = this.Tax.TaxCountryRegion, UID = this.Pk, SupUID = SupPk });
            }

            return listError.ToArray();
        }
        #endregion
    }

    public partial class Header : BaseData, IDataErrorInfo
    {
        HeaderToolTipService tooltip;
        public HeaderToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new HeaderToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get { return null; }
        }

        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "TaxRegistrationNumber")
                {
                    erro = ValidateTaxRegistrationNumber(appendError: true);
                }
                else if (columnName == "AuditFileVersion")
                {
                    erro = ValidateAuditFileVersion(appendError: true);
                }
                else if (columnName == "BusinessName")
                {
                    erro = ValidateBusinessName(appendError: true);
                }
                else if (columnName == "AddressDetail")
                {
                    erro = ValidateAddressDetail(appendError: true);
                }
                else if (columnName == "BuildingNumber")
                {
                    erro = ValidateBuildingNumber(appendError: true);
                }
                else if (columnName == "City")
                {
                    erro = ValidateCity(appendError: true);
                }
                else if (columnName == "Country")
                {
                    erro = ValidateCountry(appendError: true);
                }
                else if (columnName == "PostalCode")
                {
                    erro = ValidatePostalCode(appendError: true);
                }
                else if (columnName == "Region")
                {
                    erro = ValidateRegion(appendError: true);
                }
                else if (columnName == "StreetName")
                {
                    erro = ValidateStreetName(appendError: true);
                }
                else if (columnName == "CompanyID")
                {
                    erro = ValidateCompanyID(appendError: true);
                }
                else if (columnName == "CompanyName")
                {
                    erro = ValidateCompanyName(appendError: true);
                }
                else if (columnName == "CurrencyCode")
                {
                    erro = ValidateCurrencyCode(appendError: true);
                }
                else if (columnName == "DateCreated")
                {
                    erro = ValidateDateCreated(appendError: true);
                }
                else if (columnName == "Email")
                {
                    erro = ValidateEmail(appendError: true);
                }
                else if (columnName == "EndDate")
                {
                    erro = ValidateEndDate(appendError: true);
                }
                else if (columnName == "Fax")
                {
                    erro = ValidateFax(appendError: true);
                }
                else if (columnName == "FiscalYear")
                {
                    erro = ValidateFiscalYear(appendError: true);
                }
                else if (columnName == "HeaderComment")
                {
                    erro = ValidateHeaderComment(appendError: true);
                }
                else if (columnName == "ProductCompanyTaxID")
                {
                    erro = ValidateProductCompanyTaxID(appendError: true);
                }
                else if (columnName == "ProductID")
                {
                    erro = ValidateProductID(appendError: true);
                }
                else if (columnName == "ProductVersion")
                {
                    erro = ValidateProductVersion(appendError: true);
                }
                else if (columnName == "SoftwareCertificateNumber")
                {
                    erro = ValidateSoftwareCertificateNumber(appendError: true);
                }
                else if (columnName == "StartDate")
                {
                    erro = ValidateStartDate(appendError: true);
                }
                else if (columnName == "TaxAccountingBasis")
                {
                    erro = ValidateTaxAccountingBasis(appendError: true);
                }
                else if (columnName == "TaxEntity")
                {
                    erro = ValidateTaxEntity(appendError: true);
                }
                else if (columnName == "Telephone")
                {
                    erro = ValidateTelephone(appendError: true);
                }
                else if (columnName == "Website")
                {
                    erro = ValidateWebsite(appendError: true);
                }

                if (erro != null)
                    return erro.Description;
                else
                    return null;
            }
        }

        #region Validation
        public Error ValidateTaxRegistrationNumber(bool appendError = false)
        {
            Error erro = null;
            if (!SAFT.Validations.Validations.CheckTaxRegistrationNumber(this.TaxRegistrationNumber))
            {
                erro = new Error { Description = "NIF inválido", Field = "TaxRegistrationNumber", TypeofError = this.GetType(), Value = this.TaxRegistrationNumber, UID = this.Pk };
                if (appendError)
                    this.Tooltip.TaxRegistrationNumber = this.Tooltip.TaxRegistrationNumber.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateAuditFileVersion(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.AuditFileVersion) || this.AuditFileVersion.Length > 10)
            {
                erro = new Error { Description = "Versão do ficheiro SAF-T PT incorrecta.", Field = "AuditFileVersion", TypeofError = this.GetType(), Value = this.AuditFileVersion, UID = this.Pk };
                if (appendError)
                    this.Tooltip.AuditFileVersion = this.Tooltip.AuditFileVersion.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateBusinessName(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.BusinessName) == false)
            {
                if (this.BusinessName.Length > 60)
                {
                    erro = new Error { Description = "Designação comercial incorrecta.", Field = "BusinessName", TypeofError = this.GetType(), Value = this.BusinessName, UID = this.Pk };
                    if (appendError)
                        this.Tooltip.BusinessName = this.Tooltip.BusinessName.FormatTooltipWithError(erro.Description);
                }
            }
            return erro;
        }
        public Error ValidateAddressDetail(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.CompanyAddress.AddressDetail) || this.CompanyAddress.AddressDetail.Length > 100)
            {
                erro = new Error { Description = "Morada detalhada incorrecta.", Field = "AddressDetail", TypeofError = this.GetType(), Value = this.CompanyAddress.AddressDetail, UID = this.Pk };
                if (appendError)
                    this.Tooltip.AddressDetail = this.Tooltip.AddressDetail.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateBuildingNumber(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.CompanyAddress.BuildingNumber) && this.CompanyAddress.BuildingNumber.Length > 10)
            {
                erro = new Error { Description = "Número polícia incorrecto.", Field = "BuildingNumber", TypeofError = this.GetType(), Value = this.CompanyAddress.BuildingNumber, UID = this.Pk };
                if (appendError)
                    this.Tooltip.BuildingNumber = this.Tooltip.BuildingNumber.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateCity(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.CompanyAddress.City) || this.CompanyAddress.City.Length > 50)
            {
                erro = new Error { Description = "Localidade incorrecta.", Field = "City", TypeofError = this.GetType(), Value = this.CompanyAddress.City, UID = this.Pk };
                if (appendError)
                    this.Tooltip.City = this.Tooltip.City.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateCountry(bool appendError = false)
        {
            string country = null;
            if (this.CompanyAddress != null || this.CompanyAddress.Country != null)
                country = this.CompanyAddress.Country.ToString();

            Error erro = null;
            if (string.IsNullOrEmpty(country) || country != "PT")
            {
                erro = new Error { Description = "Localidade incorrecta.", Field = "Country", TypeofError = this.GetType(), Value = country, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Country = this.Tooltip.Country.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidatePostalCode(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.CompanyAddress.PostalCode) || this.CompanyAddress.PostalCode.Length > 50)
            {
                erro = new Error { Description = "Código postal incorrecto.", Field = "PostalCode", TypeofError = this.GetType(), Value = this.CompanyAddress.PostalCode, UID = this.Pk };
                if (appendError)
                    this.Tooltip.PostalCode = this.Tooltip.PostalCode.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateRegion(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.CompanyAddress.Region) && this.CompanyAddress.Region.Length > 50)
            {
                erro = new Error { Description = "Distrito incorrecto.", Field = "Region", TypeofError = this.GetType(), Value = this.CompanyAddress.Region, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Region = this.Tooltip.Region.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateStreetName(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.CompanyAddress.StreetName) && this.CompanyAddress.StreetName.Length > 90)
            {
                erro = new Error { Description = "Nome da rua incorrecto.", Field = "StreetName", TypeofError = this.GetType(), Value = this.CompanyAddress.StreetName, UID = this.Pk };
                if (appendError)
                    this.Tooltip.StreetName = this.Tooltip.StreetName.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateCompanyID(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.CompanyID) || this.CompanyID.Length > 50 || !Regex.IsMatch(this.CompanyID, "([0-9])+|([a-zA-Z0-9-/]+ [0-9]+)"))
            {
                if (!SAFT.Validations.Validations.CheckTaxRegistrationNumber(this.CompanyID))
                {
                    erro = new Error { Description = "Registo comercial incorrecto.", Field = "CompanyID", TypeofError = this.GetType(), Value = this.CompanyID, UID = this.Pk };
                    if (appendError)
                        this.Tooltip.CompanyID = this.Tooltip.CompanyID.FormatTooltipWithError(erro.Description);
                }
            }
            return erro;
        }
        public Error ValidateCompanyName(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.CompanyName) || this.CompanyName.Length > 100)
            {
                erro = new Error { Description = "Nome empresa incorrecto.", Field = "CompanyName", TypeofError = this.GetType(), Value = this.CompanyName, UID = this.Pk };
                if (appendError)
                    this.Tooltip.CompanyName = this.Tooltip.CompanyName.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateCurrencyCode(bool appendError = false)
        {
            Error erro = null;
            if (this.CurrencyCode == null || this.CurrencyCode.ToString() != "EUR")
            {
                erro = new Error { Description = "Código moeda incorrecto.", Field = "CurrencyCode", TypeofError = this.GetType(), Value = string.Format("{0}", this.CurrencyCode ?? "null"), UID = this.Pk };
                if (appendError)
                    this.Tooltip.CurrencyCode = this.Tooltip.CurrencyCode.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateDateCreated(bool appendError = false)
        {
            Error erro = null;
            if (this.DateCreated < Workspace.Instance.Config.MinDate || this.DateCreated > DateTime.Now)
            {
                erro = new Error { Description = "Data de criação do ficheiro incorrecta.", Field = "DateCreated", TypeofError = this.GetType(), Value = this.DateCreated.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.DateCreated = this.Tooltip.DateCreated.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateEmail(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Email) && (this.Email.Length > 60 || !Regex.IsMatch(this.Email, @"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b", RegexOptions.IgnoreCase)))
            {
                erro = new Error { Description = "Email incorrecto.", Field = "Email", TypeofError = this.GetType(), Value = this.Email, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Email = this.Tooltip.Email.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateEndDate(bool appendError = false)
        {
            Error erro = null;
            if (this.EndDate == DateTime.MinValue)
            {
                erro = new Error { Description = "Data do fim do periodo incorrecta.", Field = "EndDate", TypeofError = this.GetType(), Value = this.EndDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.EndDate = this.Tooltip.EndDate.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateFax(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Fax) && this.Fax.Length > 20)
            {
                erro = new Error { Description = "Fax incorrecto.", Field = "Fax", TypeofError = this.GetType(), Value = this.Fax, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Fax = this.Tooltip.Fax.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateFiscalYear(bool appendError = false)
        {
            Error erro = null;
            int ano = -1;
            Int32.TryParse(this.FiscalYear, out ano);
            if (string.IsNullOrEmpty(this.FiscalYear) || this.FiscalYear.Length > 4 || ano == -1)
            {
                erro = new Error { Description = "Ano fiscal incorrecto.", Field = "FiscalYear", TypeofError = this.GetType(), Value = this.FiscalYear, UID = this.Pk };
                if (appendError)
                    this.Tooltip.FiscalYear = this.Tooltip.FiscalYear.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateHeaderComment(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.HeaderComment) && this.HeaderComment.Length > 255)
            {
                erro = new Error { Description = "Comentário demasiado longo.", Field = "HeaderComment", TypeofError = this.GetType(), Value = this.HeaderComment, UID = this.Pk };
                if (appendError)
                    this.Tooltip.HeaderComment = this.Tooltip.HeaderComment.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateProductCompanyTaxID(bool appendError = false)
        {
            Error erro = null;
            if (!SAFT.Validations.Validations.CheckTaxRegistrationNumber(this.ProductCompanyTaxID))
            {
                erro = new Error { Description = "NIF da empresa produtora de saftware inválido.", Field = "ProductCompanyTaxID", TypeofError = this.GetType(), Value = this.ProductCompanyTaxID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.ProductCompanyTaxID = this.Tooltip.ProductCompanyTaxID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateProductID(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductID) || this.ProductID.Length > 255 || !this.ProductID.Contains('/'))
            {
                erro = new Error { Description = "Nome da aplicação incorrecto.", Field = "ProductID", TypeofError = this.GetType(), Value = this.ProductID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.ProductID = this.Tooltip.ProductID.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateProductVersion(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductVersion) || this.ProductVersion.Length > 30)
            {
                erro = new Error { Description = "Versão da aplicação incorrecta.", Field = "ProductVersion", TypeofError = this.GetType(), Value = this.ProductVersion, UID = this.Pk };
                if (appendError)
                    this.Tooltip.ProductVersion = this.Tooltip.ProductVersion.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateSoftwareCertificateNumber(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.SoftwareCertificateNumber) || this.SoftwareCertificateNumber.Length > 20)
            {
                erro = new Error { Description = "Número de certificação incorrecto.", Field = "SoftwareCertificateNumber", TypeofError = this.GetType(), Value = this.SoftwareCertificateNumber, UID = this.Pk };
                if (appendError)
                    this.Tooltip.SoftwareCertificateNumber = this.Tooltip.SoftwareCertificateNumber.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateStartDate(bool appendError = false)
        {
            Error erro = null;
            if (this.StartDate < Workspace.Instance.Config.MinDate)
            {
                erro = new Error { Description = "Data do início do periodo incorrecta.", Field = "StartDate", TypeofError = this.GetType(), Value = this.StartDate.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.StartDate = this.Tooltip.StartDate.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateTaxAccountingBasis(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.TaxAccountingBasis.ToString()) || this.TaxAccountingBasis.ToString().Length > 1)
            {
                erro = new Error { Description = "Sistema contabilístico incorrecto.", Field = "TaxAccountingBasis", TypeofError = this.GetType(), Value = this.TaxAccountingBasis.ToString(), UID = this.Pk };
                if (appendError)
                    this.Tooltip.TaxAccountingBasis = this.Tooltip.TaxAccountingBasis.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateTaxEntity(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.TaxEntity) || this.TaxEntity.Length > 20)
            {
                erro = new Error { Description = "Identificação do estabelecimento incorrecta.", Field = "TaxEntity", TypeofError = this.GetType(), Value = this.TaxEntity, UID = this.Pk };
                if (appendError)
                    this.Tooltip.TaxEntity = this.Tooltip.TaxEntity.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateTelephone(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Telephone) && this.Telephone.Length > 20)
            {
                erro = new Error { Description = "Identificação do estabelecimento incorrecta.", Field = "Telephone", TypeofError = this.GetType(), Value = this.Telephone, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Telephone = this.Tooltip.Telephone.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        public Error ValidateWebsite(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Website) && this.Website.Length > 60)
            {
                erro = new Error { Description = "Website incorrecto.", Field = "Website", TypeofError = this.GetType(), Value = this.Website, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Website = this.Tooltip.Website.FormatTooltipWithError(erro.Description);
            }
            return erro;
        }
        #endregion Validation
    }

    public partial class Product : BaseData, IDataErrorInfo
    {
        ProductToolTipService tooltip;
        public ProductToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new ProductToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "ProductCode")
                {
                    erro = ValidateProductCode(appendError: true);
                }
                else if (columnName == "ProductGroup")
                {
                    erro = ValidateProductGroup(appendError: true);
                }
                else if (columnName == "ProductDescription")
                {
                    erro = ValidateProductDescription(appendError: true);
                }
                else if (columnName == "ProductNumberCode")
                {
                    erro = ValidateProductNumberCode(appendError: true);
                }

                return erro == null ? "" : erro.Description;
            }
        }

        #region Validation

        public Error ValidateProductCode(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductCode) || this.ProductCode.Length > 30)
            {
                erro = new Error { Description = "Código do produto inválido", Field = "ProductCode", TypeofError = this.GetType(), Value = this.ProductCode, UID = this.Pk };
                if (appendError)
                    this.Tooltip.ProductCode = this.Tooltip.ProductCode.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateProductGroup(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.ProductGroup) && this.ProductCode.Length > 50)
            {
                erro = new Error { Description = "Família do produto ou serviço inválida", Field = "ProductGroup", TypeofError = this.GetType(), Value = this.ProductGroup, UID = this.Pk };
                if (appendError)
                    this.Tooltip.ProductGroup = this.Tooltip.ProductGroup.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateProductDescription(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductDescription) || this.ProductDescription.Length > 200)
            {
                erro = new Error { Description = "Descrição do produto ou serviço inválida", Field = "ProductDescription", TypeofError = this.GetType(), Value = this.ProductDescription, UID = this.Pk };
                if (appendError)
                    this.Tooltip.ProductDescription = this.Tooltip.ProductDescription.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateProductNumberCode(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.ProductNumberCode) || this.ProductNumberCode.Length > 50)
            {
                erro = new Error { Description = "Família do produto ou serviço inválida", Field = "ProductNumberCode", TypeofError = this.GetType(), Value = this.ProductNumberCode, UID = this.Pk };
                if (appendError)
                    this.Tooltip.ProductNumberCode = this.Tooltip.ProductNumberCode.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }

        #endregion Validation
    }

    public partial class Customer : BaseData, IDataErrorInfo
    {
        CustomerToolTipService tooltip;
        public CustomerToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new CustomerToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "CustomerID")
                {
                    erro = ValidateCustomerID(appendError: true);
                }
                else if (columnName == "AccountID")
                {
                    erro = ValidateAccountID(appendError: true);
                }
                else if (columnName == "CustomerTaxID")
                {
                    erro = ValidateCustomerTaxID(appendError: true);
                }
                else if (columnName == "CompanyName")
                {
                    erro = ValidateCompanyName(appendError: true);
                }
                else if (columnName == "Contact")
                {
                    erro = ValidateContact(appendError: true);
                }
                else if (columnName == "Telephone")
                {
                    erro = ValidateTelephone(appendError: true);
                }
                else if (columnName == "Fax")
                {
                    erro = ValidateFax(appendError: true);
                }
                else if (columnName == "Email")
                {
                    erro = ValidateEmail(appendError: true);
                }
                else if (columnName == "Website")
                {
                    erro = ValidateWebsite(appendError: true);
                }
                else if (columnName == "SelfBillingIndicator")
                {
                    erro = ValidateSelfBillingIndicator(appendError: true);
                }

                return erro == null ? "" : erro.Description;
            }
        }

        #region Validation

        public Error ValidateCustomerID(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.CustomerID) || this.CustomerID.Length > 30)
            {
                erro = new Error { Description = "Identificador único do cliente inválido", Field = "CustomerID", TypeofError = this.GetType(), Value = this.CustomerID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.CustomerID = this.Tooltip.CustomerID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateAccountID(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.AccountID) || this.AccountID.Length > 30)
            {
                erro = new Error { Description = "Código da conta inválido", Field = "AccountID", TypeofError = this.GetType(), Value = this.AccountID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.AccountID = this.Tooltip.AccountID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateCustomerTaxID(bool appendError = false)
        {
            Error erro = null;
            if (!SAFT.Validations.Validations.CheckTaxRegistrationNumber(this.CustomerTaxID))
            {
                erro = new Error { Description = "Número de identificação fiscal inválido", Field = "CustomerTaxID", TypeofError = this.GetType(), Value = this.CustomerTaxID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.CustomerTaxID = this.Tooltip.CustomerTaxID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateCompanyName(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.CompanyName) || this.CompanyName.Length > 100)
            {
                erro = new Error { Description = "Nome da empresa inválido", Field = "CompanyName", TypeofError = this.GetType(), Value = this.CompanyName, UID = this.Pk };
                if (appendError)
                    this.Tooltip.CompanyName = this.Tooltip.CompanyName.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateContact(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Contact) && this.Contact.Length > 50)
            {
                erro = new Error { Description = "Nome do contacto na empresa inválido.", Field = "Contact", TypeofError = this.GetType(), Value = this.Contact, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Contact = this.Tooltip.Contact.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateTelephone(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Telephone) && this.Telephone.Length > 20)
            {
                erro = new Error { Description = "Telefone inválido", Field = "Telephone", TypeofError = this.GetType(), Value = this.Telephone, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Telephone = this.Tooltip.Telephone.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateFax(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Fax) && this.Fax.Length > 20)
            {
                erro = new Error { Description = "Fax inválido", Field = "Fax", TypeofError = this.GetType(), Value = this.Fax, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Fax = this.Tooltip.Fax.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateEmail(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Email) && this.Email.Length > 60)
            {
                erro = new Error { Description = "Email inválido", Field = "Email", TypeofError = this.GetType(), Value = this.Email, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Email = this.Tooltip.Email.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateWebsite(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Website) && this.Website.Length > 60)
            {
                erro = new Error { Description = "Website inválido", Field = "Website", TypeofError = this.GetType(), Value = this.Website, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Website = this.Tooltip.Website.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateSelfBillingIndicator(bool appendError = false)
        {
            Error erro = null;

            int selfBillingIndicator = -1;
            if (!string.IsNullOrEmpty(this.SelfBillingIndicator))
                Int32.TryParse(this.SelfBillingIndicator, out selfBillingIndicator);

            if (string.IsNullOrEmpty(this.SelfBillingIndicator) || selfBillingIndicator == -1)
            {
                erro = new Error { Description = "Nº de conta inválido", Field = "SelfBillingIndicator", TypeofError = this.GetType(), Value = this.SelfBillingIndicator, UID = this.Pk };
                if (appendError)
                    this.Tooltip.SelfBillingIndicator = this.Tooltip.SelfBillingIndicator.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }

        public Error[] ValidateBillingAddress()
        {
            List<Error> listErro = new List<Error>();

            if (this.BillingAddress == null)
                listErro.Add(new Error { Description = "Morada de faturação inexistente", Field = "BillingAddress", TypeofError = this.GetType(), UID = this.Pk });

            if (this.BillingAddress != null)
            {
                if (string.IsNullOrEmpty(this.BillingAddress.AddressDetail) || this.BillingAddress.AddressDetail.Length > 100)
                    listErro.Add(new Error { Description = "Tamanho da morada detalhada.", Field = "AddressDetail", TypeofError = this.GetType(), Value = this.BillingAddress.AddressDetail, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.BuildingNumber) == false && this.BillingAddress.BuildingNumber.Length > 10)
                    listErro.Add(new Error { Description = "Tamanho do número de polícia incorrecto.", Field = "BuildingNumber", TypeofError = this.GetType(), Value = this.BillingAddress.BuildingNumber, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.City) || this.BillingAddress.City.Length > 50)
                    listErro.Add(new Error { Description = "Tamanho da localidade incorrecto.", Field = "City", TypeofError = this.GetType(), Value = this.BillingAddress.City, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.PostalCode) || this.BillingAddress.PostalCode.Length > 20)
                    listErro.Add(new Error { Description = "Tamanho do código postal incorrecto.", Field = "PostalCode", TypeofError = this.GetType(), Value = this.BillingAddress.PostalCode, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.Region) == false && this.BillingAddress.Region.Length > 50)
                    listErro.Add(new Error { Description = "Tamanho do distrito incorrecto.", Field = "Region", TypeofError = this.GetType(), Value = this.BillingAddress.Region, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.StreetName) == false && this.BillingAddress.StreetName.Length > 90)
                    listErro.Add(new Error { Description = "Tamanho do nome da rua incorrecto.", Field = "StreetName", TypeofError = this.GetType(), Value = this.BillingAddress.StreetName, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.Country) || (this.BillingAddress.Country.Length != 2 && this.BillingAddress.Country != "Desconhecido"))
                    listErro.Add(new Error { Description = "Tamanho do País incorrecto.", Field = "Country", TypeofError = this.GetType(), Value = this.BillingAddress.Country, UID = this.Pk });
            }

            return listErro.ToArray();
        }
        public Error[] ValidateShipToAddress()
        {
            List<Error> listErro = new List<Error>();

            if (this.ShipToAddress != null && this.ShipToAddress.Length > 0)
            {
                foreach (var morada in this.ShipToAddress)
                {
                    if (string.IsNullOrEmpty(morada.AddressDetail) || morada.AddressDetail.Length > 100)
                        listErro.Add(new Error { Description = "Tamanho da morada detalhada.", Field = "AddressDetail", TypeofError = this.GetType(), Value = morada.AddressDetail, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.BuildingNumber) == false && morada.BuildingNumber.Length > 10)
                        listErro.Add(new Error { Description = "Tamanho do número de polícia incorrecto.", Field = "BuildingNumber", TypeofError = this.GetType(), Value = morada.BuildingNumber, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.City) || morada.City.Length > 50)
                        listErro.Add(new Error { Description = "Tamanho da localidade incorrecto.", Field = "City", TypeofError = this.GetType(), Value = morada.City, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.Country) || morada.Country.Length != 2 || morada.Country != "Desconhecido")
                        listErro.Add(new Error { Description = "Tamanho do País incorrecto.", Field = "Country", TypeofError = this.GetType(), Value = morada.Country, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.PostalCode) || morada.PostalCode.Length > 20)
                        listErro.Add(new Error { Description = "Tamanho do código postal incorrecto.", Field = "PostalCode", TypeofError = this.GetType(), Value = morada.PostalCode, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.Region) == false && morada.Region.Length > 50)
                        listErro.Add(new Error { Description = "Tamanho do distrito incorrecto.", Field = "Region", TypeofError = this.GetType(), Value = morada.Region, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.StreetName) == false && morada.StreetName.Length > 90)
                        listErro.Add(new Error { Description = "Tamanho do nome da rua incorrecto.", Field = "StreetName", TypeofError = this.GetType(), Value = morada.StreetName, UID = this.Pk });
                }
            }

            return listErro.ToArray();
        }
        #endregion Validation
    }

    public partial class TaxTableEntry : BaseData, IDataErrorInfo
    {
        TaxToolTipService tooltip;
        public TaxToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new TaxToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        [System.Runtime.CompilerServices.IndexerName("Items")]
        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "TaxCountryRegion")
                {
                    erro = ValidateTaxCountryRegion(appendError: true);
                }
                else if (columnName == "TaxCode")
                {
                    erro = ValidateTaxCode(appendError: true);
                }

                return erro == null ? "" : erro.Description;
            }
        }

        #region Validations

        public Error ValidateTaxCountryRegion(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.TaxCountryRegion) || this.TaxCountryRegion.Length > 5)
            {
                erro = new Error { Description = "País ou região do imposto inválido", Field = "TaxCountryRegion", TypeofError = this.GetType(), Value = this.TaxCountryRegion, UID = this.Pk };
                if (appendError)
                    this.Tooltip.TaxCountryRegion = this.Tooltip.TaxCountryRegion.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateTaxCode(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.TaxCode) || this.TaxCode.Length > 10)
            {
                erro = new Error { Description = "Código do imposto inválido", Field = "TaxCode", TypeofError = this.GetType(), Value = this.TaxCode, UID = this.Pk };
                if (appendError)
                    this.Tooltip.TaxCode = this.Tooltip.TaxCode.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        //public Error ValidateDescription(bool appendError = false)
        //{
        //    Error erro = null;
        //    if (string.IsNullOrEmpty(this.Description) || this.Description.Length > 255)
        //    {
        //        erro = new Error { Description = "Identificador único do cliente inválido", Field = "Description", TypeofError = this.GetType(), ID = this.Description, UID = this.Pk };
        //        if (appendError)
        //            this.Tooltip.Description = this.Tooltip.Description.FormatTooltipWithError(erro.Description);
        //    }

        //    return erro;
        //}
        //public Error ValidateTaxExpirationDate(bool appendError = false)
        //{
        //    Error erro = null;
        //    if (string.IsNullOrEmpty(this.TaxExpirationDate) || this.TaxExpirationDate.Length > 30)
        //    {
        //        erro = new Error { Description = "Data de fim de vigência inválida", Field = "TaxExpirationDate", TypeofError = this.GetType(), ID = this.TaxExpirationDate, UID = this.Pk };
        //        if (appendError)
        //            this.Tooltip.TaxExpirationDate = this.Tooltip.TaxExpirationDate.FormatTooltipWithError(erro.Description);
        //    }

        //    return erro;
        //}
        //public Error ValidateTaxPercentage(bool appendError = false)
        //{
        //    Error erro = null;
        //    if (string.IsNullOrEmpty(this.TaxPercentage) || this.TaxPercentage.Length > 30)
        //    {
        //        erro = new Error { Description = "Percentagem da taxa do imposto inválida.", Field = "TaxPercentage", TypeofError = this.GetType(), ID = this.TaxPercentage, UID = this.Pk };
        //        if (appendError)
        //            this.Tooltip.TaxPercentage = this.Tooltip.TaxPercentage.FormatTooltipWithError(erro.Description);
        //    }

        //    return erro;
        //}
        //public Error ValidateTaxAmount(bool appendError = false)
        //{
        //    Error erro = null;
        //    if (string.IsNullOrEmpty(this.TaxAmount) || this.TaxAmount.Length > 30)
        //    {
        //        erro = new Error { Description = "Identificador único do cliente inválido", Field = "TaxAmount", TypeofError = this.GetType(), ID = this.TaxAmount, UID = this.Pk };
        //        if (appendError)
        //            this.Tooltip.TaxAmount = this.Tooltip.TaxAmount.FormatTooltipWithError(erro.Description);
        //    }

        //    return erro;
        //}
        #endregion
    }

    public partial class Supplier : BaseData, IDataErrorInfo
    {
        SupplierToolTipService tooltip;
        public SupplierToolTipService Tooltip
        {
            get
            {
                if (tooltip == null)
                    tooltip = new SupplierToolTipService();
                return tooltip;
            }
            set { tooltip = value; }
        }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get
            {
                Error erro = null;
                if (columnName == "CustomerID")
                {
                    erro = ValidateCustomerID(appendError: true);
                }
                else if (columnName == "AccountID")
                {
                    erro = ValidateAccountID(appendError: true);
                }
                else if (columnName == "SupplierTaxID")
                {
                    erro = ValidateSupplierTaxID(appendError: true);
                }
                else if (columnName == "CompanyName")
                {
                    erro = ValidateCompanyName(appendError: true);
                }
                else if (columnName == "Contact")
                {
                    erro = ValidateContact(appendError: true);
                }
                else if (columnName == "Telephone")
                {
                    erro = ValidateTelephone(appendError: true);
                }
                else if (columnName == "Fax")
                {
                    erro = ValidateFax(appendError: true);
                }
                else if (columnName == "Email")
                {
                    erro = ValidateEmail(appendError: true);
                }
                else if (columnName == "Website")
                {
                    erro = ValidateWebsite(appendError: true);
                }
                else if (columnName == "SelfBillingIndicator")
                {
                    erro = ValidateSelfBillingIndicator(appendError: true);
                }

                return erro == null ? "" : erro.Description;
            }
        }

        #region Validation

        public Error ValidateCustomerID(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.SupplierID) || this.SupplierID.Length > 30)
            {
                erro = new Error { Description = "Identificador único do fornecedor inválido", Field = "SupplierID", TypeofError = this.GetType(), Value = this.SupplierID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.SupplierID = this.Tooltip.SupplierID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateAccountID(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.AccountID) || this.AccountID.Length > 30)
            {
                erro = new Error { Description = "Código da conta inválido", Field = "AccountID", TypeofError = this.GetType(), Value = this.AccountID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.AccountID = this.Tooltip.AccountID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateSupplierTaxID(bool appendError = false)
        {
            Error erro = null;
            if (!SAFT.Validations.Validations.CheckTaxRegistrationNumber(this.SupplierTaxID))
            {
                erro = new Error { Description = "Número de identificação fiscal inválido", Field = "SupplierTaxID", TypeofError = this.GetType(), Value = this.SupplierTaxID, UID = this.Pk };
                if (appendError)
                    this.Tooltip.SupplierTaxID = this.Tooltip.SupplierTaxID.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateCompanyName(bool appendError = false)
        {
            Error erro = null;
            if (string.IsNullOrEmpty(this.CompanyName) || this.CompanyName.Length > 100)
            {
                erro = new Error { Description = "Nome da empresa inválido", Field = "CompanyName", TypeofError = this.GetType(), Value = this.CompanyName, UID = this.Pk };
                if (appendError)
                    this.Tooltip.CompanyName = this.Tooltip.CompanyName.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateContact(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Contact) && this.Contact.Length > 50)
            {
                erro = new Error { Description = "Nome do contacto na empresa inválido.", Field = "Contact", TypeofError = this.GetType(), Value = this.Contact, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Contact = this.Tooltip.Contact.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateTelephone(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Telephone) && this.Telephone.Length > 20)
            {
                erro = new Error { Description = "Telefone inválido", Field = "Telephone", TypeofError = this.GetType(), Value = this.Telephone, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Telephone = this.Tooltip.Telephone.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateFax(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Fax) && this.Fax.Length > 20)
            {
                erro = new Error { Description = "Fax inválido", Field = "Fax", TypeofError = this.GetType(), Value = this.Fax, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Fax = this.Tooltip.Fax.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateEmail(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Email) && this.Email.Length > 60)
            {
                erro = new Error { Description = "Email inválido", Field = "Email", TypeofError = this.GetType(), Value = this.Email, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Email = this.Tooltip.Email.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateWebsite(bool appendError = false)
        {
            Error erro = null;
            if (!string.IsNullOrEmpty(this.Website) && this.Website.Length > 60)
            {
                erro = new Error { Description = "Website inválido", Field = "Website", TypeofError = this.GetType(), Value = this.Website, UID = this.Pk };
                if (appendError)
                    this.Tooltip.Website = this.Tooltip.Website.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }
        public Error ValidateSelfBillingIndicator(bool appendError = false)
        {
            Error erro = null;

            int selfBillingIndicator = -1;
            if (!string.IsNullOrEmpty(this.SelfBillingIndicator))
                Int32.TryParse(this.SelfBillingIndicator, out selfBillingIndicator);

            if (string.IsNullOrEmpty(this.SelfBillingIndicator) || selfBillingIndicator == -1)
            {
                erro = new Error { Description = "Nº de conta inválido", Field = "SelfBillingIndicator", TypeofError = this.GetType(), Value = this.SelfBillingIndicator, UID = this.Pk };
                if (appendError)
                    this.Tooltip.SelfBillingIndicator = this.Tooltip.SelfBillingIndicator.FormatTooltipWithError(erro.Description);
            }

            return erro;
        }

        public Error[] ValidateBillingAddress()
        {
            List<Error> listErro = new List<Error>();

            if (this.BillingAddress == null)
                listErro.Add(new Error { Description = "Morada de faturação inexistente", Field = "BillingAddress", TypeofError = this.GetType(), UID = this.Pk });

            if (this.BillingAddress != null)
            {
                if (string.IsNullOrEmpty(this.BillingAddress.AddressDetail) || this.BillingAddress.AddressDetail.Length > 100)
                    listErro.Add(new Error { Description = "Tamanho da morada detalhada.", Field = "AddressDetail", TypeofError = this.GetType(), Value = this.BillingAddress.AddressDetail, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.BuildingNumber) == false && this.BillingAddress.BuildingNumber.Length > 10)
                    listErro.Add(new Error { Description = "Tamanho do número de polícia incorrecto.", Field = "BuildingNumber", TypeofError = this.GetType(), Value = this.BillingAddress.BuildingNumber, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.City) || this.BillingAddress.City.Length > 50)
                    listErro.Add(new Error { Description = "Tamanho da localidade incorrecto.", Field = "City", TypeofError = this.GetType(), Value = this.BillingAddress.City, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.Country) || this.BillingAddress.Country.Length != 2)
                    listErro.Add(new Error { Description = "Tamanho do País incorrecto.", Field = "Country", TypeofError = this.GetType(), Value = this.BillingAddress.Country, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.PostalCode) || this.BillingAddress.PostalCode.Length > 20)
                    listErro.Add(new Error { Description = "Tamanho do código postal incorrecto.", Field = "PostalCode", TypeofError = this.GetType(), Value = this.BillingAddress.PostalCode, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.Region) == false && this.BillingAddress.Region.Length > 50)
                    listErro.Add(new Error { Description = "Tamanho do distrito incorrecto.", Field = "Region", TypeofError = this.GetType(), Value = this.BillingAddress.Region, UID = this.Pk });
                if (string.IsNullOrEmpty(this.BillingAddress.StreetName) == false && this.BillingAddress.StreetName.Length > 90)
                    listErro.Add(new Error { Description = "Tamanho do nome da rua incorrecto.", Field = "StreetName", TypeofError = this.GetType(), Value = this.BillingAddress.StreetName, UID = this.Pk });
            }

            return listErro.ToArray();
        }
        public Error[] ValidateShipFromAddress()
        {
            List<Error> listErro = new List<Error>();

            if (this.ShipFromAddress != null && this.ShipFromAddress.Length > 0)
            {
                foreach (var morada in this.ShipFromAddress)
                {
                    if (string.IsNullOrEmpty(morada.AddressDetail) || morada.AddressDetail.Length > 100)
                        listErro.Add(new Error { Description = "Tamanho da morada detalhada.", Field = "AddressDetail", TypeofError = this.GetType(), Value = morada.AddressDetail, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.BuildingNumber) == false && morada.BuildingNumber.Length > 10)
                        listErro.Add(new Error { Description = "Tamanho do número de polícia incorrecto.", Field = "BuildingNumber", TypeofError = this.GetType(), Value = morada.BuildingNumber, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.City) || morada.City.Length > 50)
                        listErro.Add(new Error { Description = "Tamanho da localidade incorrecto.", Field = "City", TypeofError = this.GetType(), Value = morada.City, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.Country) || morada.Country.Length != 2)
                        listErro.Add(new Error { Description = "Tamanho do País incorrecto.", Field = "Country", TypeofError = this.GetType(), Value = morada.Country, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.PostalCode) || morada.PostalCode.Length > 20)
                        listErro.Add(new Error { Description = "Tamanho do código postal incorrecto.", Field = "PostalCode", TypeofError = this.GetType(), Value = morada.PostalCode, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.Region) == false && morada.Region.Length > 50)
                        listErro.Add(new Error { Description = "Tamanho do distrito incorrecto.", Field = "Region", TypeofError = this.GetType(), Value = morada.Region, UID = this.Pk });
                    if (string.IsNullOrEmpty(morada.StreetName) == false && morada.StreetName.Length > 90)
                        listErro.Add(new Error { Description = "Tamanho do nome da rua incorrecto.", Field = "StreetName", TypeofError = this.GetType(), Value = morada.StreetName, UID = this.Pk });
                }
            }

            return listErro.ToArray();
        }
        #endregion Validation
    }

    public partial class GeneralLedger : BaseData, IDataErrorInfo
    {

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get { throw new NotImplementedException(); }
        }
    }

    public partial class GeneralLedgerEntriesJournal : BaseData, IDataErrorInfo
    {
        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get { throw new NotImplementedException(); }
        }
    }

    public partial class GeneralLedgerEntriesJournalTransaction : BaseData, IDataErrorInfo
    {
        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        [System.Runtime.CompilerServices.IndexerName("Items")]
        public string this[string columnName]
        {
            get { throw new NotImplementedException(); }
        }
    }

    public partial class GeneralLedgerEntriesJournalTransactionLine : BaseData, IDataErrorInfo
    {
        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        [System.Runtime.CompilerServices.IndexerName("Items")]
        public string this[string columnName]
        {
            get { throw new NotImplementedException(); }
        }
    }

    public partial class SchemaResults { }

    public partial class HashResults { }
}
